diff options
-rw-r--r-- | docs/conf/modules.conf.example | 17 | ||||
-rw-r--r-- | src/modules/m_websocket.cpp | 27 |
2 files changed, 39 insertions, 5 deletions
diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 639f02335..9cb78daee 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -2307,11 +2307,18 @@ # Requires SHA-1 hash support available in the sha1 module. #<module name="websocket"> # -# Whether to re-encode messages as UTF-8 before sending to WebSocket -# clients. This is recommended as the WebSocket protocol requires all -# text frames to be sent as UTF-8. If you do not have this enabled -# messages will be sent as binary frames instead. -#<websocket sendastext="yes"> +# behindproxy: Whether the server is behind a proxy that sends the +# X-Real-IP or X-Forwarded-For headers. If enabled the +# server will use the IP address specified by those HTTP +# headers. You should NOT enable this unless you are using +# a HTTP proxy like nginx as it will allow IP spoofing. +# sendastext: Whether to re-encode messages as UTF-8 before sending to +# WebSocket clients. This is recommended as the WebSocket +# protocol requires all text frames to be sent as UTF-8. +# If you do not have this enabled messages will be sent as +# binary frames instead. +#<websocket behindproxy="no" +# sendastext="yes"> # # If you use the websocket module you MUST specify one or more origins # which are allowed to connect to the server. You should set this as diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 3437fdb1a..79cabf4e5 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -36,6 +36,9 @@ struct WebSocketConfig // The HTTP origins that can connect to the server. OriginList allowedorigins; + // Whether to trust the X-Real-IP or X-Forwarded-For headers. + bool behindproxy; + // Whether to send as UTF-8 text instead of binary data. bool sendastext; }; @@ -340,6 +343,29 @@ class WebSocketHook : public IOHookMiddle return -1; } + if (config.behindproxy && sock->type == StreamSocket::SS_USER) + { + LocalUser* luser = static_cast<UserIOHandler*>(sock)->user; + irc::sockets::sockaddrs realsa(luser->client_sa); + + HTTPHeaderFinder proxyheader; + if (proxyheader.Find(recvq, "X-Real-IP:", 10, reqend) + && irc::sockets::aptosa(proxyheader.ExtractValue(recvq), realsa.port(), realsa)) + { + // Nothing to do here. + } + else if (proxyheader.Find(recvq, "X-Forwarded-For:", 16, reqend) + && irc::sockets::aptosa(proxyheader.ExtractValue(recvq), realsa.port(), realsa)) + { + // Nothing to do here. + } + + // Give the user their real IP address. + if (realsa != luser->client_sa) + luser->SetClientIP(realsa); + } + + HTTPHeaderFinder keyheader; if (!keyheader.Find(recvq, "Sec-WebSocket-Key:", 18, reqend)) { @@ -492,6 +518,7 @@ class ModuleWebSocket : public Module } ConfigTag* tag = ServerInstance->Config->ConfValue("websocket"); + config.behindproxy = tag->getBool("behindproxy"); config.sendastext = tag->getBool("sendastext", true); // Everything is okay; apply the new config. |