[英]How can I make my TCP listening app safer?
我正在尋找有關編寫一個非常安全的C / C ++應用程序(可偵聽TCP端口)的建議。 我想看看其他人正在嘗試對我的機器做什么,但是如果我可以用一個很短的程序就能完成我所需要的工作,我寧願不安裝一個精心設計的蜜罐應用程序。 為了我的目標既簡單又安全,我要確保至少處理以下各項:
1)客戶端不應發送無限量的數據,
2)客戶端不應通過過多的連接使服務器過載,並且
3)客戶端不應能夠無限期地保持連接打開。
由於我當前的應用程序很小且功能正常,因此似乎對該項目不需要第三方庫。 但是,一個可以簡化應用程序的小型庫將很有趣。 另外,我希望C ++標准庫可以幫助簡化我的代碼。
以下是我最初嘗試時的一些關鍵功能。 該代碼在Windows,OSX和Linux上編譯。
如何使應用程序更安全或更簡單?
void SafeClose(SOCKET s)
{
if (s == INVALID_SOCKET)
return;
shutdown(s, SHUT_RDWR);
closesocket(s);
}
void ProcessConnection(SOCKET sock, sockaddr_in *sockAddr)
{
time_t time1;
char szTime[TIME_BUF_SIZE];
char readBuf[READ_BUF_SIZE];
time(&time1);
strftime(szTime, TIME_BUF_SIZE-1, "%Y/%m/%d %H:%M:%S", localtime(&time1));
printf("%s - %s\n", szTime, inet_ntoa(sockAddr->sin_addr));
usleep(1000000); // Wait 1 second for client to send something
int actualReadCount = recv(sock, readBuf, READ_BUF_SIZE-1, 0);
if (actualReadCount < 0 || actualReadCount >= READ_BUF_SIZE){
actualReadCount = 0;
strcpy(readBuf, "(Nothing)");
} else {
CleanString(readBuf, actualReadCount); // Replace non-printable characters
readBuf[actualReadCount] = 0;
}
printf("%s\n\n", readBuf);
SafeClose(sock);
}
int main(int argc, char* argv[])
{
int port = 80;
char cmd[CMD_BUF_SIZE] = {0};
sockaddr_in newSockAddr;
sockaddr_in localSockAddr;
if(argc < 2){
printf("Usage: safelisten PORT\n\n");
return error_code;
}
error_code++;
port = atoi(argv[1]);
BuildCleanAsciiMap(); // Used to replace non-printable characters
localSockAddr.sin_family = AF_INET;
localSockAddr.sin_addr.s_addr = INADDR_ANY;
localSockAddr.sin_port = htons(port);
sizeNewSockAddr = sizeof newSockAddr;
CHK( listenSocket = socket(AF_INET, SOCK_STREAM, 0));
CHK( setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)));
CHK( bind(listenSocket, (sockaddr*)&localSockAddr, sizeof localSockAddr));
CHK( listen(listenSocket, BACKLOG));
CHK( SetNonBlocking(listenSocket));
CHK( SetNonBlocking(0)); // Set STDIN to nonblocking for linux
printf ("Listening on port: %d\nEnter q to quit.\n\n", port);
while(strcmp(cmd, "q")) // While the user has not entered q ...
{
newSocket = accept(listenSocket, (sockaddr*)&newSockAddr, &sizeNewSockAddr);
ReadCmd(cmd, CMD_BUF_SIZE);
if(newSocket == INVALID_SOCKET) {
// accept() would have blocked, thus we wait and try again
usleep(10000);
continue;
}
// Set to nonblocking because we don't want the client to dictate how
// long we are connected.
CHK( SetNonBlocking(newSocket));
ProcessConnection(newSocket, &newSockAddr);
}
SafeClose(listenSocket);
return 0;
}
2)客戶端不應通過太多連接使服務器過載...
最好的選擇是讓路由器限制IP地址建立的連接數,因為當程序獲得連接信息時,已經分配了系統資源。
1)客戶端不應發送無限量的數據,
最好的選擇是擁有一個可以發送的合理最大值,並跟蹤已閱讀的數量,一旦達到最大值,就關閉連接。
3)客戶端不應能夠無限期地保持連接打開。
為此,您可以僅創建一個將啟動倒計時的線程,因此當連接在特定時間段內打開時,它可能會超時並且您可以僅關閉連接。
還有其他更復雜的解決方案,但是我認為這將是一個很好的起點。
如果您想對(2)做一些事情,請將哈希圖保存在內存中,並僅增加已建立的連接數,但您可能還想跟蹤時間。 您希望數據結構非常快,因此可以決定是否需要盡早斷開連接。
例如,如果哈希圖中有兩個long,則可以輸入第一個連接的時間(以unixtime或ticks為單位),然后遞增;如果在不到一分鍾的時間內獲得10個連接,則開始關閉多余的連接,直到一分鍾過去了。 如果該元素的連接時間足夠長,以至於您相信它沒有在攻擊您,則將其刪除。
另外,請確保您驗證傳遞給您的所有參數,並對任何字符串都具有合理的最大值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.