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