我正在寻找有关编写一个非常安全的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;
}
答案 0 :(得分:1)
2)客户端也不应该使服务器过载 很多联系...
您最好的选择是让路由器限制IP地址的连接数,因为当您的程序获得连接信息时,已经分配了系统资源。
1)客户端无法发送无限量的数据,
最好的选择是获得一些可以发送的合理最大值,并且只记录您已阅读的数量,一旦达到最大限制,请关闭连接。
3)客户端无法无限期地保持连接打开。
为此,您可以创建一个将开始倒计时的线程,因此当连接打开一段特定时间时,它可以超时,您可以关闭连接。
还有其他更复杂的解决方案,但我认为这将是一个很好的起点。
如果你想对(2)做一些事情,请在内存中保留一个hashmap,只增加已建立的连接数,但你可能还想跟踪时间。您希望数据结构非常快,因此您可以决定是否需要尽早断开连接。
例如,如果你在hashmap中有两个long,那么你可以把第一个连接的时间(在unixtime或ticks中)和增量,如果你在不到一分钟内得到10个连接,就开始关闭过剩直到一分钟过去了。然后删除该元素,如果它有足够长的连接,你相信它没有攻击你。
另外,请确保验证传递给您的所有参数,并为任何字符串设置合理的最大值。