如何让我的TCP监听应用程序更安全?

时间:2011-10-02 19:25:33

标签: c++ tcp listen honeypot

我正在寻找有关编写一个非常安全的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;
}

1 个答案:

答案 0 :(得分:1)

  

2)客户端也不应该使服务器过载   很多联系...

您最好的选择是让路由器限制IP地址的连接数,因为当您的程序获得连接信息时,已经分配了系统资源。

  

1)客户端无法发送无限量的数据,

最好的选择是获得一些可以发送的合理最大值,并且只记录您已阅读的数量,一旦达到最大限制,请关闭连接。

  

3)客户端无法无限期地保持连接打开。

为此,您可以创建一个将开始倒计时的线程,因此当连接打开一段特定时间时,它可以超时,您可以关闭连接。

还有其他更复杂的解决方案,但我认为这将是一个很好的起点。

如果你想对(2)做一些事情,请在内存中保留一个hashmap,只增加已建立的连接数,但你可能还想跟踪时间。您希望数据结构非常快,因此您可以决定是否需要尽早断开连接。

例如,如果你在hashmap中有两个long,那么你可以把第一个连接的时间(在unixtime或ticks中)和增量,如果你在不到一分钟内得到10个连接,就开始关闭过剩直到一分钟过去了。然后删除该元素,如果它有足够长的连接,你相信它没有攻击你。

另外,请确保验证传递给您的所有参数,并为任何字符串设置合理的最大值。

相关问题