diff options
-rw-r--r-- | docs/conf/modules.conf.example | 8 | ||||
-rw-r--r-- | src/modules/m_websocket.cpp | 26 |
2 files changed, 23 insertions, 11 deletions
diff --git a/docs/conf/modules.conf.example b/docs/conf/modules.conf.example index 9cb78daee..cee785436 100644 --- a/docs/conf/modules.conf.example +++ b/docs/conf/modules.conf.example @@ -2307,9 +2307,9 @@ # Requires SHA-1 hash support available in the sha1 module. #<module name="websocket"> # -# 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 +# proxyranges: A space-delimited list of glob or CIDR matches to trust +# the X-Real-IP or X-Forwarded-For headers from. 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 @@ -2317,7 +2317,7 @@ # 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" +#<websocket proxyranges="192.0.2.0/24 198.51.100.*" # sendastext="yes"> # # If you use the websocket module you MUST specify one or more origins diff --git a/src/modules/m_websocket.cpp b/src/modules/m_websocket.cpp index 79cabf4e5..ee1c00e97 100644 --- a/src/modules/m_websocket.cpp +++ b/src/modules/m_websocket.cpp @@ -33,11 +33,13 @@ static dynamic_reference_nocheck<HashProvider>* sha1; struct WebSocketConfig { + typedef std::vector<std::string> ProxyRanges; + // 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; + // The IP ranges which send trustworthy X-Real-IP or X-Forwarded-For headers. + ProxyRanges proxyranges; // Whether to send as UTF-8 text instead of binary data. bool sendastext; @@ -343,7 +345,7 @@ class WebSocketHook : public IOHookMiddle return -1; } - if (config.behindproxy && sock->type == StreamSocket::SS_USER) + if (!config.proxyranges.empty() && sock->type == StreamSocket::SS_USER) { LocalUser* luser = static_cast<UserIOHandler*>(sock)->user; irc::sockets::sockaddrs realsa(luser->client_sa); @@ -360,9 +362,16 @@ class WebSocketHook : public IOHookMiddle // Nothing to do here. } - // Give the user their real IP address. - if (realsa != luser->client_sa) - luser->SetClientIP(realsa); + for (WebSocketConfig::ProxyRanges::const_iterator iter = config.proxyranges.begin(); iter != config.proxyranges.end(); ++iter) + { + if (InspIRCd::MatchCIDR(*iter, luser->GetIPString(), ascii_case_insensitive_map)) + { + // Give the user their real IP address. + if (realsa == luser->client_sa) + luser->SetClientIP(realsa); + break; + } + } } @@ -518,9 +527,12 @@ class ModuleWebSocket : public Module } ConfigTag* tag = ServerInstance->Config->ConfValue("websocket"); - config.behindproxy = tag->getBool("behindproxy"); config.sendastext = tag->getBool("sendastext", true); + irc::spacesepstream proxyranges(tag->getString("proxyranges")); + for (std::string proxyrange; proxyranges.GetToken(proxyrange); ) + config.proxyranges.push_back(proxyrange); + // Everything is okay; apply the new config. hookprov->config = config; } |