这是我的 iptables 脚本:
#!/bin/sh
service iptables stop
iptables -F
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp --sport 53 --dport 1024:65535 -j ACCEPT
service iptables save
service iptables restart
它在 Centos 6.3 上运行良好,但在 Centos 6.0 上我无法建立出站 HTTP 连接。(我可能无法建立任何出站 TCP/IP 连接。)但是,DNS 查找工作正常,显然基于 UDP 的其他任何操作也都正常。
我猜这与 TCP 的三次握手有关,而我对此几乎一无所知。既然如此,其中一个模块的版本肯定存在差异,早期版本需要明确指定INPUT
规则才能允许握手。那么,我需要创建哪些规则才能允许 TCP 握手并因此接收数据?
答案1
您的系统将从临时端口发起连接。
一般来说,不要试图比 netfilter 的 conntrack 更聪明。
任何合适的规则集中的第一个规则应该是iptables -m conntrack --ctstate ESTABLISHED -j ACCEPT
(仅-m state
当您的发行版缺少时才使用-m conntrack
) - 这样做将使您的系统启动出站连接并成功接收回复。
此外,为了节省资源,iptables -t raw -A PREROUTING -i lo -j CT --notrack
(或-j NOTRACK
)以及iptables -t raw -A OUTPUT -o lo -j CT --notrack
INPUT 和 OUTPUT 链中的适当规则以允许--ctstate UNTRACKED
将节省在环回连接上不必要地消耗 conntrack 资源。
答案2
这有效(见评论):
#!/bin/sh
service iptables stop
iptables -F
# Unlike the script in the question, incoming TCP packets are allowed in by default.
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
# Allow all loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow incoming SSH, HTTP and HTTPS
iptables -A INPUT -p tcp -m multiport --dports 22,80,443 -m state --state NEW,ESTABLISHED -j ACCEPT
# Allow DNS responses
iptables -A INPUT -p udp --sport 53 --dport 1024:65535 -j ACCEPT
# This is new: Drop all incoming TCP packets with the SYN bit set.
iptables -A INPUT -p tcp --syn -m state --state NEW -j DROP
service iptables save
service iptables restart
我使用 netcat 对此进行了非常彻底的测试。