这实际上是一个由两部分组成的问题。请记住,我是一名开发人员,而不是系统管理员,但作为公司中唯一的员工,我身兼所有职务。
我在服务器上部署了两台防火墙,它们运行在 CARP 上以实现负载平衡/冗余,另外还部署了大约 40 台计算机以满足数据库和其他后端应用程序的需求。作为一家初创公司,我想通过减轻 DDoS 攻击造成的损失来节省一些资金,而无需向 ISP 支付 DDoS 保护之外的企业专用互联网费用。我知道你无法完全防范 DDoS。我只想减轻损失,直到我的应用程序开始赚钱,然后我就可以让 ISP 来解决这些麻烦。
本着这种精神,我想知道是否有人实施过一种解决方案,即使用脚本(可能通过 cron)根据当前使用情况更改 PF 规则。例如,如果来自数百万个 IP 地址的半开连接过多,我想告诉 PF 进入 SYN-Cookies 模式,然后在攻击结束(或经过一段时间后)恢复正常。
我无法使用 Cloudfare,因为我正在运行应用程序的后端,并且 99% 的内容都不是静态的。我可以为应用程序的网站使用 Cloudfare,但仅此而已。
重申一下,钱是个问题。我目前正在使用 FIOS Business,Verizon 不会在这种类型的线路上提供 DDoS 保护。
最后,有人在启用 SYN-COOKIES/SYN-PROXYING 后遇到过严重问题吗?请告诉我真实情况。
PS:我不想开始关于 SYN-PROXYING 与 SYN-COOKIES 的争论!
答案1
由于没有人回答我的问题,因此这是我最终采用的 pf 配置。具体来说,请查看在表中填充了 15% 的开放 tcp 连接后设置 cookie 的行。SYN Cookies 在防止过多半开放连接方面非常有效。但这并非最终结果。您可以在自己的环境中执行的另一件事是将外部接口上的 icmp 数量限制为每秒 1000 个。这是我仍需研究的东西。只是不要在您的网络内部限制它,因为这可能会产生毁灭性的影响。
bogons 表和 USA 表经常更新。分别每 4 小时和 24 小时更新一次。这是必须的,因为有许多 IP 地址(尤其是 ipv6)目前未使用。那么为什么还要处理它们呢?另外,美国以外的任何人都不需要通过 SSH 进行访问。
还有几个暴力尝试表,我的应用程序从外部更新,ssh 在 pf 内更新。以防有人试图同时尝试太多连接,他们显然是在尝试一些可疑的事情。
这不是我的最终配置,因为我对我的网络服务器和其他东西进行了负载平衡,但不想发布太多不必要的信息。
最后要注意的是,总是尝试运行 carp 来实现故障转移/冗余/负载平衡!
# Macros
udp_services = "{ domain, ntp }"
tcp_services = "{ ssh, smtp, domain, www, pop3, auth, https, pop3s }"
carpdevs = "carp0"
ext_if = "em0"
int_if = "{ em1, em2, em3, em4, em5 }"
localnet = "{ em1:network, em2:network, em3:network, em4:network, em5:network}"
table <USA_IP_ADDRESSES> persist file "/etc/usa_all_ip.zone"
table <dhcpd_leased_ips> persist
table <dhcpd_abandoned_ips> persist
table <dhcpd_changed_ips> persist
table <bruteforce> persist
table <bogons> persist file "/etc/bogons" # see cron jobs for when this file gets updated (daily) and from where
table <lan> const { 192.168.1.0/24, 192.168.2.0/24, 192.168.3.0/24, 192.168.4.0/24, 192.168.5.0 }
table <webservers> persist { 192.168.4.10, 192.168.4.20 }
table <websiteoverload> persist
table <appoverload> persist
table <mysmateservers> persist
# Global settings
set debug warning
set limit { states 10000000, table-entries 1000000}
set optimization aggressive
set syncookies adaptive (start 15%, end 8%)
set timeout tcp.established 1800
set skip on lo
set loginterface em0
# Default everything coming in + antispoof
antispoof for $ext_if inet
antispoof for $int_if inet
antispoof for carp0 inet
block drop all
block drop in quick on $ext_if from { <bogons>, <bruteforce> }
# Allow traffic from all our CARP devices
pass on $carpdevs proto carp
# Allow connections between all of our intrefaces
pass from { self, $localnet }
#block drop in on $ext_if from carp0:network
# block all outgoing traffic through em0 coming from em2-em5 and don't bother testing other rules
block return out on egress proto { tcp, udp} from 192.168.0.0/16
# pass out clock synchronization
pass out on egress proto udp from 192.168.0.0/16 to port ntp
# pass out dns look up
pass out on egress proto { udp, tcp } from 192.168.0.0/16 to port domain
pass out on egress from 192.168.1.0/24
pass out on egress from 192.168.5.0/24
pass out log on egress from 192.168.2.0/24
match out on $ext_if inet from 192.168.0.0/16 nat-to (carp0) # NAT, match IPv4 only
# ICMP related rules -- See The PF Book Chapter 3
icmp_types = "{ echoreq, unreach }"
icmp6_types = "{ echoreq unreach timex paramprob }"
pass inet proto icmp icmp-type $icmp_types #max-pkt-rate 100/1
pass inet6 proto icmp6 icmp6-type $icmp6_types # max-pkt-rate 100/1
# Allow default port range for traceroute(8) 64*3 - Reference: The PF Book Chapter 3
pass out on egress inet proto udp to port 33433:33626 # For IPv4
pass out on egress inet6 proto udp to port 33433:33626 # For IPv6
# Allow incoming SSH connections from US IP addresses only
pass in log on $ext_if proto tcp from <USA_IP_ADDRESSES> to port ssh modulate state \
(max-src-conn 50, max-src-conn-rate 10/1, overload <bruteforce> flush global)
# Allow incoming traffic on http,https and forward it to our web_server computer
pass in log on $ext_if proto tcp from <USA_IP_ADDRESSES> to port https rdr-to 192.168.5.5 keep state \
(max-src-conn-rate 100/1, overload <websiteoverload>)
pass in log on $ext_if proto tcp from <USA_IP_ADDRESSES> to port 58777 rdr-to <mysmateservers> least-states modulate state \
(max-src-conn-rate 1000/1, overload <appoverload>)
# By default, do not permit remote connections to X11
block return in on ! lo0 proto tcp to port 6000:6010
# Port build user does not need network
block return out proto {tcp udp} user _pbuild