我有一个用 C/C++ 编写的代码,如下所示:
while(1)
{
//Accept
struct sockaddr_in client_addr;
int client_fd = this->w_accept(&client_addr);
char client_ip[64];
int client_port = ntohs(client_addr.sin_port);
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip));
//Listen first string
char firststring[512];
memset(firststring,0,512);
if(this->recvtimeout(client_fd,firststring,sizeof(firststring),u->timeoutlogin) < 0){
close(client_fd);
}
if(strcmp(firststring,"firststr")!=0)
{
cout << "Disconnected!" << endl;
close(client_fd);
continue;
}
//Send OK first string
send(client_fd, "OK", 2, 0);
//Listen second string
char secondstring[512];
memset(secondstring,0,512);
if(this->recvtimeout(client_fd,secondstring,sizeof(secondstring),u->timeoutlogin) < 0){
close(client_fd);
}
if(strcmp(secondstring,"secondstr")!=0)
{
cout << "Disconnected!!!" << endl;
close(client_fd);
continue;
}
//Send OK second string
send(client_fd, "OK", 2, 0);
}
}
所以,它是可以的。 我用 perl 编写了一个非常简单的 dos 脚本来关闭服务器。
#Evildos.pl
use strict;
use Socket;
use IO::Handle;
sub dosfunction
{
my $host = shift || '192.168.4.21';
my $port = 1234;
my $firststr = 'firststr';
my $secondstr = 'secondstr';
my $protocol = getprotobyname('tcp');
$host = inet_aton($host) or die "$host: unknown host";
socket(SOCK, AF_INET, SOCK_STREAM, $protocol) or die "socket() failed: $!";
my $dest_addr = sockaddr_in($port,$host);
connect(SOCK,$dest_addr) or die "connect() failed: $!";
SOCK->autoflush(1);
print SOCK $firststr;
#sleep(1);
print SOCK $secondstr;
#sleep(1);
close SOCK;
}
my $i;
for($i=0; $i<30;$i++)
{
&dosfunction;
}
循环30次,服务器宕机。
问题是:是否有方法、系统、解决方案可以避免此类攻击?
编辑:recvtimeout
int recvtimeout(int s, char *buf, int len, int timeout)
{
fd_set fds;
int n;
struct timeval tv;
// set up the file descriptor set
FD_ZERO(&fds);
FD_SET(s, &fds);
// set up the struct timeval for the timeout
tv.tv_sec = timeout;
tv.tv_usec = 0;
// wait until timeout or data received
n = select(s+1, &fds, NULL, NULL, &tv);
if (n == 0){
return -2; // timeout!
}
if (n == -1){
return -1; // error
}
// data must be here, so do a normal recv()
return recv(s, buf, len, 0);
}
最佳答案
一般来说,我认为没有任何 100% 有效的 DOS 攻击软件解决方案;无论您做什么,总有人会向您的网络接口(interface)抛出超出其处理能力的更多数据包。
不过,在这种特殊情况下,看起来您的程序一次只能处理一个连接——也就是说,在连接 #1 完成其事务(或超时)之前,传入连接 #2 不会被处理.所以这是一个明显的瓶颈——攻击者所要做的就是连接到您的服务器,然后什么都不做,您的服务器将被有效禁用(无论您的超时时间有多长)。
为避免这种情况,您需要重写服务器代码以同时处理多个 TCP 连接。您可以通过切换到非阻塞 I/O(通过将 O_NONBLOCK 标志传递给 fcntl()),并使用 select() 或 poll() 等来一次等待多个套接字上的 I/O,或者通过生成多个线程或子进程以并行处理传入连接,或使用异步 I/O。 (我个人更喜欢第一种解决方案,但都可以在不同程度上起作用)。在第一种方法中,在接受来自该 IP 地址的新套接字之前强行关闭来自给定 IP 地址的任何现有套接字之类的操作也是实用的,这意味着任何给定的攻击计算机最多只能占用您的一个套接字服务器,这将使该人更难对您的机器进行 DOS 操作,除非他可以访问多个客户端机器。
你可能会读到 this article有关同时处理多个 TCP 连接的更多讨论。
关于c++ - 如何在这段代码中避免 DOS 攻击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10787062/