我尝试编写规则来保护仅使用 http/https、apt-get 更新、发送邮件 SSH 访问的 Web 服务器。到目前为止,我已经做到了:
IPT=/sbin/iptables
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT DROP
#
$IPT -A INPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
#
# Allow All for SSH
$IPT -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --sport 22 -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --dport 22 -j ACCEPT
#
# Allow all for HTTP / HTTPS
$IPT -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -i eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
#
# Allow loopback traffic
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
#
# Allow to be pinged ( Outside => srv )
$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$IPT -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
#
# Allow outgoing DNS connections
$IPT -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
$IPT -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
#
# Apt-get
$IPT -A OUTPUT -p tcp --dport 80 --sport 32786:61000 -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 --sport 32786:61000 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 32786:61000 --sport 80 -j ACCEPT
$IPT -A INPUT -p tcp --dport 32786:61000 --sport 80 -j ACCEPT
#
# SMTP Outgoing
$IPT -A OUTPUT -p tcp --sport 1024:65535 -d 0/0 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -p tcp -s 0/0 --sport 25 --dport 1024:65535 -m state --state ESTABLISHED-j ACCEPT
#
# Prevent DoS
#$IPT -A INPUT -p tcp --dport 80 -m limit --limit 60/minute --limit-burst 150 -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 100 --connlimit-mask 32 -j REJECT --reject-with tcp-reset
#
# Log dropped packets
$IPT -N LOGGING
$IPT -A INPUT -j LOGGING
$IPT -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: " --log-level 7
$IPT -A LOGGING -j DROP
#
$IPT -L
但似乎我错过了一些让传出 SSH 正常工作的东西(从此服务器到远程,另一种方法有效),但我找不到是什么。我还尝试通过输入 IP 来 ssh 目标,以防某些 DNS 内容被阻止,但这也不起作用。
我非常确定这些规则是它不起作用的原因,因为如果我尝试刷新并接受所有内容,它就会运行良好。
以下是 iptables -L -n 的输出:
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 state NEW,ESTABLISHED
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:443 state ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 8
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp spt:53
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spts:32786:61000 dpt:80
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 dpts:32786:61000
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:25 dpts:1024:65535 state ESTABLISHED
REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 #conn/32 > 100 reject-with tcp-reset
LOGGING all -- 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy DROP)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 state ESTABLISHED
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 state NEW,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 0
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:53
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spts:32786:61000 dpt:80
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 dpts:32786:61000
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spts:1024:65535 dpt:25 state NEW,ESTABLISHED
Chain LOGGING (1 references)
target prot opt source destination
LOG all -- 0.0.0.0/0 0.0.0.0/0 limit: avg 2/min burst 5 LOG flags 0 level 7 prefix `IPTables Packet Dropped: '
DROP all -- 0.0.0.0/0 0.0.0.0/0
答案1
当您有传出连接时,目标端口将为 22,因此规则应为:
$IPT -A OUTPUT -o eth0 -p tcp --dport 22 -j ACCEPT
此外,您应该有一条规则来涵盖ESTABLISHED
和位于和链RELATED
之上:INPUT
OUTPUT
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
希望这可以帮助。
答案2
您的传出 SSH 流量规则不包含NEW
启动传出连接所需的语句。
答案3
如果你不了解客户端-服务器架构和“状态防火墙”,这是一个典型的错误
在客户端-服务器架构中,唯一可预先知道的端口是目标端口,因为客户端会选择一个临时端口1,除了一些极其罕见的例外,例如 DHCP。
从防火墙的角度来看,从防火墙驱逐的每个数据包都具有 NEW 状态,尤其是在 TCP 连接中。2
首先让我们看看我们有什么
IPT=/sbin/iptables
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT DROP
# Excellent!! because always we need to accept this kind of states because
# always are response packets, remember we can be client or server
$IPT -A INPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
# Allow All for SSH
# this accept ssh connections from outside, and the response for this input
# is a outgoing packet with the state ESTABLISHED. (four lines above)
$IPT -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
# this rule are meaningless because you never start a ssh connection from
# source port 22, this because the source ports are choose randomly
$IPT -A OUTPUT -o eth0 -p tcp --sport 22 -j ACCEPT
# this one let start a ssh connection from within to the outside and the response
# enter in state ESTABLISHED, 13 lines above
$IPT -A OUTPUT -o eth0 -p tcp --dport 22 -j ACCEPT
# Allow all for HTTP / HTTPS
# http servers are very basic if we think on client-server, they only respond a
# client request, except if some web software try to establish a network connection
# to the outside, for this block the only rule with meaning is the first, the rest are
# meaningless
$IPT -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -o eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -i eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
# Allow loopback traffic
# this are obligatory rules avoiding the firewall block himself
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Allow to be pinged ( Outside => srv )
# always the interpretation depends from the point of view
# with this rules you can accept ping request from outside and despond the request
# but you cannot ping from inside to outside because in that scenario you send the request (OUTPUT)
# and receive a reply from outside (INPUT)
$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$IPT -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
# Allow outgoing DNS connections
# this allow send dns queries to the DNS server that you have registered in the file
# /etc/resolv.conf
$IPT -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
# this one are meaningless because the response from the DNS server is ESTABLISHED and is
# accepted in the very beginning in the firewall
$IPT -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
# Apt-get
# AFAIK apt use http or ftp, they can use https but is less common
# the specification of a range on source port are meaningless
$IPT -A OUTPUT -p tcp --dport 80 --sport 32786:61000 -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 --sport 32786:61000 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 32786:61000 --sport 80 -j ACCEPT
$IPT -A INPUT -p tcp --dport 32786:61000 --sport 80 -j ACCEPT
# SMTP Outgoing
# I don't known why you start adding more criteria without meaning
# maybe you start surfing on the net and starting copy&paste code without see what you are doing
# always when yo need to learn something go to the root, or in this case to www.netfilter.org
$IPT -A OUTPUT -p tcp --sport 1024:65535 -d 0/0 --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
$IPT -A INPUT -p tcp -s 0/0 --sport 25 --dport 1024:65535 -m state --state ESTABLISHED-j ACCEPT
# the rules below are.... copy&paste from somewhere
# Prevent DoS
#$IPT -A INPUT -p tcp --dport 80 -m limit --limit 60/minute --limit-burst 150 -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 100 --connlimit-mask 32 -j REJECT --reject-with tcp-reset
#
# Log dropped packets
$IPT -N LOGGING
$IPT -A INPUT -j LOGGING
$IPT -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Dropped: " --log-level 7
$IPT -A LOGGING -j DROP
所以对我来说,你需要这个防火墙
IPT=/sbin/iptables
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT DROP
# accept a priori all the responses
$IPT -A INPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
$IPT -A OUTPUT -m state --STATE ESTABLISHED,RELATED -j ACCEPT
# Allow All for SSH
# allow ssh connections from outside to inside
$IPT -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
# allow ssh connections from inside to outside
$IPT -A OUTPUT -o eth0 -p tcp --dport 22 -j ACCEPT
# Allow all for HTTP / HTTPS
$IPT -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
$IPT -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT
# Allow loopback traffic
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Allow to be pinged ( Outside => srv )
$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$IPT -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
# from srv to outside
$IPT -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
$IPT -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT
# Allow outgoing DNS connections
$IPT -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
# Apt-get
$IPT -A OUTPUT -p tcp --dport 80 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 21 -j ACCEPT
# SMTP Outgoing
$IPT -A OUTPUT -p tcp --dport 25 -j ACCEPT
希望对您有所帮助。抱歉,我的英语不是我的母语。
答案4
对于最简单的规则(暂时忽略状态):
iptables -A INPUT -p tcp --sport 22 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT
这应该可以解决问题。一旦您尝试并成功,您可以修改它以包含状态、源/目标 IP 地址、不同的端口......