如何设置 iptables 以阻止对服务器的传入请求,但仍然具有互联网连接

Bad*_*nda 2 networking firewall iptables

我的服务器上正在运行多个服务。但我不希望他们接触互联网。我的输入链规则看起来像这样

-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-port-unreachable
Run Code Online (Sandbox Code Playgroud)

但这会阻止与我的服务器的互联网连接,并 sudo apt update引发此错误

W:无法获取http://in.archive.ubuntu.com/ubuntu/dists/jammy/InRelease 解决“in.archive.ubuntu.com”的临时失败

ping www.google.com失败

ping: www.google.com : 名称解析暂时失败

这看起来是 DNS 的问题,但我相信规则 4 应该可以解决这个问题。对此的任何帮助将不胜感激。谢谢!

crdy@kronos:~$ ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 60:eb:69:5a:a4:42 brd ff:ff:ff:ff:ff:ff
3: wlp2s0b1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 4c:0f:6e:8f:fa:ee brd ff:ff:ff:ff:ff:ff
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:21:72:43:ee brd ff:ff:ff:ff:ff:ff
5: br-644e9cb757d7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default 
    link/ether 02:42:d1:97:64:3f brd ff:ff:ff:ff:ff:ff
7: veth83dfd13@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default 
    link/ether d2:50:90:b9:56:a2 brd ff:ff:ff:ff:ff:ff link-netnsid 0
9: veth45fe61a@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-644e9cb757d7 state UP mode DEFAULT group default 
    link/ether 0a:63:2f:70:4b:8a brd ff:ff:ff:ff:ff:ff link-netnsid 1
11: veth7e52459@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-644e9cb757d7 state UP mode DEFAULT group default 
    link/ether 7a:ca:83:21:b9:a6 brd ff:ff:ff:ff:ff:ff link-netnsid 2
crdy@kronos:~$ ip -br addr
lo               UNKNOWN        127.0.0.1/8 ::1/128 
enp1s0           UP             192.168.29.118/24 metric 100 2405:201:c027:305d:62eb:69ff:fe5a:a442/64 fe80::62eb:69ff:fe5a:a442/64 
wlp2s0b1         DOWN           
docker0          UP             172.17.0.1/16 fe80::42:21ff:fe72:43ee/64 
br-644e9cb757d7  UP             172.24.0.1/16 fe80::42:d1ff:fe97:643f/64 
veth83dfd13@if6  UP             fe80::d050:90ff:feb9:56a2/64 
veth45fe61a@if8  UP             fe80::863:2fff:fe70:4b8a/64 
veth7e52459@if10 UP             fe80::78ca:83ff:fe21:b9a6/64 
crdy@kronos:~$ ip route
default via 192.168.29.1 dev enp1s0 proto dhcp src 192.168.29.118 metric 100 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 
172.24.0.0/16 dev br-644e9cb757d7 proto kernel scope link src 172.24.0.1 
192.168.29.0/24 dev enp1s0 proto kernel scope link src 192.168.29.118 metric 100 
192.168.29.1 dev enp1s0 proto dhcp scope link src 192.168.29.118 metric 100 
crdy@kronos:~$ ip rule
0:  from all lookup local
32766:  from all lookup main
32767:  from all lookup default
crdy@kronos:~$ sudo iptables-save -c
[sudo] password for crdy: 
Sorry, try again.
[sudo] password for crdy: 
# Generated by iptables-save v1.8.7 on Sat Feb 24 18:28:34 2024
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
[1025:108099] -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[4168:296903] -A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
[2571:174714] -A INPUT -j REJECT --reject-with icmp-port-unreachable
[13462:3748285] -A FORWARD -j DOCKER-USER
[13462:3748285] -A FORWARD -j DOCKER-ISOLATION-STAGE-1
[230:453506] -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[0:0] -A FORWARD -o docker0 -j DOCKER
[242:17392] -A FORWARD -i docker0 ! -o docker0 -j ACCEPT
[0:0] -A FORWARD -i docker0 -o docker0 -j ACCEPT
[12982:3276891] -A FORWARD -o br-644e9cb757d7 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
[7:420] -A FORWARD -o br-644e9cb757d7 -j DOCKER
[1:76] -A FORWARD -i br-644e9cb757d7 ! -o br-644e9cb757d7 -j ACCEPT
[7:420] -A FORWARD -i br-644e9cb757d7 -o br-644e9cb757d7 -j ACCEPT
[0:0] -A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 9443 -j ACCEPT
[0:0] -A DOCKER -d 172.24.0.2/32 ! -i br-644e9cb757d7 -o br-644e9cb757d7 -p tcp -m tcp --dport 22300 -j ACCEPT
[0:0] -A DOCKER -d 172.24.0.3/32 ! -i br-644e9cb757d7 -o br-644e9cb757d7 -p tcp -m tcp --dport 5432 -j ACCEPT
[0:0] -A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 9000 -j ACCEPT
[0:0] -A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8000 -j ACCEPT
[242:17392] -A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
[1:76] -A DOCKER-ISOLATION-STAGE-1 -i br-644e9cb757d7 ! -o br-644e9cb757d7 -j DOCKER-ISOLATION-STAGE-2
[13462:3748285] -A DOCKER-ISOLATION-STAGE-1 -j RETURN
[0:0] -A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
[0:0] -A DOCKER-ISOLATION-STAGE-2 -o br-644e9cb757d7 -j DROP
[243:17468] -A DOCKER-ISOLATION-STAGE-2 -j RETURN
[13462:3748285] -A DOCKER-USER -j RETURN
COMMIT
# Completed on Sat Feb 24 18:28:34 2024
# Generated by iptables-save v1.8.7 on Sat Feb 24 18:28:34 2024
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:DOCKER - [0:0]
[418:12363] -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
[1:60] -A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
[12:874] -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
[1:76] -A POSTROUTING -s 172.24.0.0/16 ! -o br-644e9cb757d7 -j MASQUERADE
[0:0] -A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 9443 -j MASQUERADE
[0:0] -A POSTROUTING -s 172.24.0.2/32 -d 172.24.0.2/32 -p tcp -m tcp --dport 22300 -j MASQUERADE
[0:0] -A POSTROUTING -s 172.24.0.3/32 -d 172.24.0.3/32 -p tcp -m tcp --dport 5432 -j MASQUERADE
[0:0] -A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 9000 -j MASQUERADE
[0:0] -A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 8000 -j MASQUERADE
[0:0] -A DOCKER -i docker0 -j RETURN
[0:0] -A DOCKER -i br-644e9cb757d7 -j RETURN
[0:0] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 9443 -j DNAT --to-destination 172.17.0.2:9443
[0:0] -A DOCKER ! -i br-644e9cb757d7 -p tcp -m tcp --dport 9665 -j DNAT --to-destination 172.24.0.2:22300
[0:0] -A DOCKER ! -i br-644e9cb757d7 -p tcp -m tcp --dport 5432 -j DNAT --to-destination 172.24.0.3:5432
[0:0] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 9445 -j DNAT --to-destination 172.17.0.2:9000
[0:0] -A DOCKER ! -i docker0 -p tcp -m tcp --dport 8000 -j DNAT --to-destination 172.17.0.2:8000
COMMIT
# Completed on Sat Feb 24 18:28:34 2024
Run Code Online (Sandbox Code Playgroud)

A.B*_*A.B 5

添加的iptables规则会阻止系统访问自身以获得自己的服务。如果 DNS 服务器正在系统上运行并使用主机的主地址或 127.0.0.1 进行查询,则系统无法再访问它本身。通过插入规则以允许此类访问来修复此问题:

iptables -I INPUT -i lo -j ACCEPT
Run Code Online (Sandbox Code Playgroud)

配置的时候只要把这个规则放在前面即可(然后就可以用-A代替-I)。


此外,由于该REJECT规则及其可能的意外影响(最近)中描述iptables-extensions(8)

警告:您不应不加区别地将 REJECT 目标应用于连接状态分类为 INVALID 的数据包;相反,你应该只删除这些。

[跳过有关延迟重传 TCP 数据包触发类似 bug 行为的详细说明]

这可能会使合法(通常是长期存在的)TCP 连接意外终止。

至少对于6.1REJECT之前的内核,如果保留规则而不是本身更改为DROP(为了提高安全性,如已经评论的那样),则应使用以下内容:

-I INPUT -m conntrack --ctstate INVALID -j DROP
Run Code Online (Sandbox Code Playgroud)

它可以放在任何地方,只要它位于REJECT规则之前即可。

  • @Bad_Panda 许多(大多数?)发行版都设置为使用本地缓存解析器来处理 DNS 查找,几乎在所有情况下都通过让它侦听环回接口,并将系统上的其他所有内容都指向该接口作为主 DNS 服务器。这通常只是将请求转发到上游服务器,但拥有它(并使用它)可以显着减少对大多数典型 DNS 使用模式的外部 DNS 流量的需求。 (3认同)
  • @Bad_Panda也就是说,您并没有通过阻止环回接口上的流量来提高安全性(任何可以向那里发送数据包的人都已经有能力在您的系统上运行任意代码,因此他们可能会在不需要它的情况下导致大量其他问题),并且它很可能最终会破坏 DNS 以外的其他东西,因此您可能应该保留规则以允许环回接口上的流量。 (2认同)
  • @Bad_Panda:Ubuntu 使用 SystemD-ResolveD 进行 DNS 解析。SystemD-ResolveD 专为高度动态的网络环境而设计,例如云虚拟机在服务器之间实时迁移、移动设备动态更改 WiFi 网络、或在 WiFi 和移动设备之间更改、笔记本电脑插拔、笔记本电脑进入睡眠状态在一种环境中醒来,却在完全不同的环境中醒来。因此,Ubuntu 默认情况下不使用 `/etc/resolv.conf` 中的静态名称服务器。对于绕过标准 Unix 名称解析并直接读取 `/etc/resolv.con` 的应用程序,SystemD-ResolveD (2认同)
  • ...在 127.0.0.53 上运行“代理”名称服务器并将该地址放入“/etc/resolv.conf”中。这样,即使应用程序绕过 SystemD-ResolveD 或 NSS 并直接读取“/etc/resolv.conf”,也能保证以与使用 NSS 或直接使用 SystemD-ResolveD 的应用程序相同的方式解析地址。您是否想要和/或需要它,是一个不同的问题。默认情况下,“/etc/resolv.conf”是“/run/systemd/resolve/stub-resolv.conf”的符号链接,由 SystemD-ResolveD 动态更新。 (2认同)