簡體   English   中英

如何使TCP監聽應用程序更安全?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM