Add a limit of 10 unidentified connections per IP

Everything which isn't a CClient with a successful login counts as an
unidentified connection in this context. Modules who don't want this kind of
limit on their listening sockets can override CSocket::ConnectionFrom(), but
their sockets will still count towards this limit.


git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1561 726aef4b-f618-498e-8847-2d620e286838
This commit is contained in:
psychon
2009-07-10 13:27:55 +00:00
parent 39364f057f
commit b25e65dbb6
7 changed files with 45 additions and 1 deletions

View File

@@ -85,6 +85,8 @@ public:
SetMaxBufferThreshold(1024);
StartLoginTimeout();
SetNick("unknown-nick");
}
virtual ~CClient();

View File

@@ -145,6 +145,10 @@ void CSocket::SockError(int iErrno) {
}
}
bool CSocket::ConnectionFrom(const CString& sHost, unsigned short uPort) {
return CZNC::Get().AllowConnectionFrom(sHost);
}
bool CSocket::Connect(const CString& sHostname, unsigned short uPort, bool bSSL, unsigned int uTimeout) {
CUser* pUser = m_pModule->GetUser();
CString sSockName = "MOD::C::" + m_pModule->GetModName();

View File

@@ -151,6 +151,9 @@ public:
// This defaults to closing the socket, feel free to override
virtual void ReachedMaxBuffer();
virtual void SockError(int iErrno);
// This limits the global connections from this IP to defeat DoS
// attacks, feel free to override
virtual bool ConnectionFrom(const CString& sHost, unsigned short uPort);
bool Connect(const CString& sHostname, unsigned short uPort, bool bSSL = false, unsigned int uTimeout = 60);
bool Listen(unsigned short uPort, bool bSSL = false, unsigned int uTimeout = 0);

View File

@@ -191,3 +191,20 @@ int CZNCSock::GetAddrInfo(const CS_STRING &sHostname, CSSockAddr &csSockAddr) {
return 0;
}
#endif
unsigned int CSockManager::GetAnonConnectionCount(const CString &sIP) const {
const_iterator it;
unsigned int ret = 0;
for (it = begin(); it != end(); it++) {
CZNCSock *pSock = *it;
// Logged in CClients have "USR::<username>" as their sockname
if (pSock->GetRemoteIP() == sIP && pSock->GetSockName().Left(5) != "USR::") {
ret++;
}
}
DEBUG("There are [" << ret << "] clients from [" << sIP << "]");
return ret;
}

View File

@@ -98,6 +98,8 @@ public:
return TSocketManager<CZNCSock>::Connect(C, pcSock);
}
unsigned int GetAnonConnectionCount(const CString &sIP) const;
private:
protected:
#ifdef HAVE_ARES

View File

@@ -399,6 +399,12 @@ bool CZNC::IsHostAllowed(const CString& sHostMask) const {
return false;
}
bool CZNC::AllowConnectionFrom(const CString& sIP) const {
if (GetManager().GetAnonConnectionCount(sIP) >= 10)
return false;
return true;
}
void CZNC::InitDirs(const CString& sArgvPath, const CString& sDataDir) {
char *home;

12
znc.h
View File

@@ -37,6 +37,8 @@ public:
CUser* GetUser(const CString& sUser);
Csock* FindSockByName(const CString& sSockName);
bool IsHostAllowed(const CString& sHostMask) const;
// This returns false if there are too many anonymous connections from this ip
bool AllowConnectionFrom(const CString& sIP) const;
void InitDirs(const CString& sArgvPath, const CString& sDataDir);
bool OnBoot();
CString ExpandConfigPath(const CString& sConfigFile);
@@ -86,6 +88,7 @@ public:
// Getters
bool GetNeedRehash() const { return m_bNeedRehash; }
CSockManager& GetManager() { return m_Manager; }
const CSockManager& GetManager() const { return m_Manager; }
#ifdef _MODULES
CGlobalModules& GetModules() { return *m_pModules; }
#endif
@@ -175,9 +178,16 @@ public:
virtual Csock* GetSockObj(const CString& sHost, unsigned short uPort) {
CClient *pClient = new CClient(sHost, uPort);
if (CZNC::Get().AllowConnectionFrom(sHost))
#ifdef _MODULES
CZNC::Get().GetModules().OnClientConnect(pClient, sHost, uPort);
CZNC::Get().GetModules().OnClientConnect(pClient, sHost, uPort);
#endif
else {
pClient->RefuseLogin("Too many anonymous connections from your IP");
#ifdef _MODULES
CZNC::Get().GetModules().OnFailedLogin("", sHost);
#endif
}
return pClient;
}