服务器不套cloudflare,硬抗DDOS攻击研究------内核过滤篇

一个典型的HTTP服务器的网络扑朔大概长这样

277817e7222d17aac35924c330e61a7a.png</s>277817e7222d17aac35924c330e61a7a.png<e>

很典型的LNMP配置,对外提供HTTP服务


-----

可以看出,流量的第一站是BGP路由网络(公网)->再到机房路由->再到区域子网(同掩码)->再到服务器kernel,kernel取出对应端口tcp数据包。重组为tcp流。然后发给上级application层(如nginx,apache等等的recv())


----
##### 流量的第一站【BGP路由网络(公网)】只有运营商可以控制,我们也配置不了:huaji06:。略过。

586f7dce7b2f80211372d93861cc2355.png![586f7dce7b2f80211372d93861cc2355.png](https://s.rmimg.com/2024/03/12/586f7dce7b2f80211372d93861cc2355.png)

>!

现代厂商生产的路由器基本CVE-2016-3116都用不了。有些直接开的telnetd,没加密,只有IP白名单限制(这个安全限制其实很傻逼,如果控制了相邻BPG路由器,源IP可以完全伪造。横向日过去),如果只开console ttl,暂时没法(前提是ttl没入公网)。总之这里暂时略过。运营商的路由器基本都是买的(思科,华为之类的),系统一般不是Linux,像bsd之类的。这是真的路由器(路由器的定义),不是tplink的那种家庭nat“路由器”


----

#### 流量的第二站【上级机房路由网关】这是很重要的,如果Server一被打,就直接被机房上级路由空路由。那么服务器再怎么配置都是没有的。因为流量根本就不会到达子网。服务端根本收不到任何数据。所以要选不拔线的“高防机房”。

>!

如果你能进去的话,这个就暂时不提。这里讲的是正常用户能配置的地方,哈哈哈

cc7eccb9b78f543a7e723b5cc2535fa6.png![cc7eccb9b78f543a7e723b5cc2535fa6.png](https://s.rmimg.com/2024/03/12/cc7eccb9b78f543a7e723b5cc2535fa6.png)


-----

#### 内核部分,流量到达服务器首先会被内核处理。然后才到应用层。所以内核过滤一份,会明显减小应用层处理的压力。


----

6f8275a47708f8c2ac9754e87e244117.png![6f8275a47708f8c2ac9754e87e244117.png](https://s.rmimg.com/2024/03/12/6f8275a47708f8c2ac9754e87e244117.png)

### 在应用层处理的话,会涉及明显的用户态与内核态之间切换。已以及数据频繁的从用户态与内核态的拷贝。造成的明显的后果是占用大量内存。


----

#### 下面就简单的说一下,内核是正常用户能配置最外层地方(openvz,lxc等等没法)

**下面的抗DD配置是针对http server优化的**,如果你的服务器跑的不是http服务,下面配置会有负面效果。

部分参考了经典的C1000K问题。

##### 禁用udp连接,仅仅允许udp53(dns),udp123(时间同步)端口的通信。

http1.1,http2主要是tcp连接
http3是udp连接,QUIC现在依然会发生反射放大攻击。现在并没有完全解决。建议暂时不开。

禁用udp流量,udp洪水确实不好防,加上udp是无状态的。而且源IP可以伪造

禁用udp新连接入站

>

iptables -A INPUT -p udp -m state –state NEW -j DROP

仅允许dns和时间同步ntp数据包出站

>

iptables -A OUTPUT -p udp –dport 53 -j ACCEPT

> iptables -A OUTPUT -p udp –dport 123 -j ACCEPT

> iptables -A OUTPUT -p udp -j DROP

##### 如果服务器是dhcp网络,记得把67,68端口打开

>

iptables -A OUTPUT -p udp –dport 67 -j ACCEPT

> iptables -A OUTPUT -p udp –dport 68 -j ACCEPT

##### icmp洪水攻击,很简单,禁用ping就行。或者限制icmp包的频率。这个iptables防火墙可以配置

-----
##### 然后应对tcp层面的攻击

-----

### tcp syn攻击防御, tcp syn攻击就不解释了,自己去查。

注意syn是tcp连接前的数据包,IP可以伪造。

通过调整内核参数,来减小攻击的影响

>

/proc/sys/net/ipv4/tcp_syn_retries TCP SYN 连接超时重传次数

> /proc/sys/net/ipv4/tcp_synack_retries 连接超时回复超时次数

> /proc/sys/net/ipv4/tcp_retries2 TCP SYN 连接重传次数限制

这些太大,服务器会被大量空syn占用资源,增加内核负担


-----

#### TCP队列等待参数

>

/proc/sys/net/ipv4/tcp_ecn 每个IP头部会被设置ECN位,服务器会检查发送端和接收端,动态调整网络拥塞。

ECN正常使用没什么问题,但是这在被ddos的情况下,反而会成为一直负担。ddos会有大量无效流量。

>

/proc/sys/net/ipv4/tcp_abort_on_overflow 当某IP的TCP请求连接队列溢出时,丢弃新的连接请求,避免请求无限排队卡死。


-----

>

/proc/sys/net/ipv4/tcp_keepalive_probes 用于检测处于空闲状态的 TCP 连接是否仍然有效。防止大量空连接攻击

> /proc/sys/net/ipv4/tcp_fin_timeout FIN-WAIT结束时间,默认太长。对于被恶意攻击,会被占用大量资源。

> /proc/sys/net/ipv4/tcp_keepalive_intvl 用于设置TCP keepalive探测包的发送间隔时间。具体来说,这个参数定义了在发送两个连续的TCP keepalive探测包之间的时间间隔, 30就够了

> /proc/sys/net/ipv4/tcp_keepalive_time 当一个TCP连接处于空闲状态(即没有数据传输)时,系统会定期发送TCP keepalive探测包以检测连接的状态。如果远程端未响应这些探测包,系统将认为连接已经断开,并关闭连接,释放资源。

> /proc/sys/net/ipv4/tcp_notsent_lowat TCP发送缓冲区的低水位标记,1G当未发送数据达到该值时,触发发送。防止数据堆积,tcp慢读取攻击。默认太高,这个也不能设置的太低。

> tcp_max_tw_buckets 用于限制处于TIME-WAIT状态的TCP连接的数量。TIME-WAIT状态是指在TCP连接关闭后,等待一段时间以确保远端接收到最后的ACK确认消息的状态,可以限制系统中允许处于TIME-WAIT状态的TCP连接数量,避免消耗过多的系统资源。


----
##### 开启bbr

>

echo bbr > /proc/sys/net/ipv4/tcp_congestion_control 避免DDOS高宽带拥塞导致服务器速度过低


-----

#### 文件描述符fd

##### Linux的文件描述符fd是什么?,自己去查。

简单来说linux的每个打开的socket和accept都是fd

>

cat /proc/sys/fs/file-max 最大接收连接,大于100万就没事。

>

/proc/sys/fs/inotify/max_user_instances 每个用户能够创建的inotify实例的最大数量。这个限制是为了防止某个用户或应用程序过度使用系统资源。但是对于http服务器来说,基本只有www-data会占用网络文件描述符。如果太低会出现too many open files。拒绝服务

>/proc/sys/fs/inotify/max_user_watches 决定了某个用户的内核事件的监听fd的最大文件数量,与epoll事件有关。如果没用epoll可以忽略。

>cat /proc/sys/fs/nr_open 单用户进程最大打开文件数量 大于65536就行

#### 另外,tcp_syncookies 要开启,防止大量syn洪水。

>

/proc/sys/net/ipv4/ip_local_port_range 反代设置的13270 - 65100就行,如果不反代,正常使用不用管。如果范围太小,连接后端会出现连接数不够用。把502错误。

#### 这里说一下,Linux最大连接tcp连接数不是65536,是connect()函数的**单IP**的tcp限制为65536,加一个sub就能突破65536了。而对于server端的accept()函数是没有限制的,除非系统限制。

connect()函数只和客户端请求和服务器反代后端会用到,**具体自己查,就不说了**

>

cat /proc/sys/net/ipv4/tcp_tw_reuse 大于1 减少time wait的时间

>

/proc/sys/net/core/somaxconn 设置系统上accept套接字的最大连接数。和accept()函数有关

>

/proc/sys/net/ipv4/tcp_max_syn_backlog 设置TCP半连接队列的最大长度,用于存放未完成连接的请求。

> /proc/sys/net/core/netdev_max_backlog 设置网络设备接收队列的最大长度。

#### 描述符设置

>

ulimit -n 65535

### iptables 链表设置,如果没用iptables可以忽略。

net.nf_conntrack_max
net.netfilter.nf_conntrack_max

net.nf_conntrack_max 和 net.netfilter.nf_conntrack_max:这两个参数通常被设置为相同的值,它们设置了nf_conntrack模块可以跟踪的最大连接数。此值设置为8388608意味着你的系统将能够跟踪多达多个并发连接。如果这个值设置得太低,则在高流量的情况下可能导致跟踪表满,从而阻止新的连接建立。

net.netfilter.nf_conntrack_tcp_timeout_fin_wait
net.netfilter.nf_conntrack_tcp_timeout_time_wait

此参数设置了在FIN-WAIT状态下的TCP连接在被系统自动删除之前可以保持打开状态的时间,此处设置为60秒。

这个参数指定了TIME-WAIT状态下的TCP连接在系统中保持的时间,60秒。


----

net.netfilter.nf_conntrack_tcp_timeout_close_wait

设置CLOSE-WAIT状态下的TCP连接保持的时间,设置为30秒。

#### 端口内核态限制速率

##### 内核态的速率限制比用户态的效率高很多

80 端口 IP在60秒内只允许新建80个连接
iptables -A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m recent --set --name DEFAULT --rsource

第一个匹配到NEW状态连接在端口80的规则,它用来记录新的连接。

iptables -A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -m recent --update --seconds 60 --hitcount 100 --name DEFAULT --rsource -j DROP


基于第一条规则收集的数据,如果一个IP地址在60秒内尝试了超过100次新连接,则阻止(DROP)这个IP的新连接请求。

#### 控制单个IP的最大并发连接数为80

iptables -I INPUT -p tcp --dport 80 -m connlimit --connlimit-above 80 -j REJECT

#### 每个IP最多120个初始syn

iptables -A INPUT -p tcp --syn -m connlimit --connlimit-above 120 -j DROP


----

#### 配置完后,可以尽可能减小应用层服务处理的压力。应用层再进行进一步处理

webserver -> php-runtime - > *.php -> SQL,尽量不用让流量到达后面。越到后面处理的花费的性能越大。

6f8275a47708f8c2ac9754e87e244117.png![6f8275a47708f8c2ac9754e87e244117.png](https://s.rmimg.com/2024/03/12/6f8275a47708f8c2ac9754e87e244117.png)


-----

如果能再上级网关路由处理,上硬件防火墙当然是最好的。运营商路由拦截也是很好的,不过正常人是不可能的操作的。


-----

**下次再写应用层处理的思路吧**


------

说过题外话,论坛的cpu占用过高。

35025fc44e78b539b83f4f808a8c6265.png![35025fc44e78b539b83f4f808a8c6265.png](https://s.rmimg.com/2024/03/12/35025fc44e78b539b83f4f808a8c6265.png)

大佬带着重磅产品重返江湖。

最终还得高防哈,哈哈,网络上始终那套太多了,想搞人的始终会来,所以只能一步一步慢慢去完善

字多就对

@“Benladen”#p17509 好的,下次少写一点:huaji06:

@“[未知用户]”#p17515 我的错,这两天好多事。马上给你。

>

@“[未知用户]”#p17501 说过题外话,论坛的cpu占用过高。

应该是全部是js渲染的原因,这也是现在最让我头大的地方。

学习学习了,虽然最后还是要高防加WAF,但是能优化高防加WAF后还是能多抗一些

多写点 晚点我搬走

硬抗DDNS?

大佬明示站长了 站长还不表示表示

来学习学习。虽然看不懂:huaji06:

跟着大佬学习

大佬太厉害了,看不懂