2

I have multiple services that are running on my server. But I do not want them to be exposed to internet. My input chain rules look something like this

-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

But this blocks the internet connectivity to my server, sudo apt update throws this error

W: Failed to fetch http://in.archive.ubuntu.com/ubuntu/dists/jammy/InRelease Temporary failure resolving 'in.archive.ubuntu.com'

and ping www.google.com fails with

ping: www.google.com: Temporary failure in name resolution

It looks an issue with DNS but I believe rule 4 should take care of that. Any help on this would be appreciated. Thanks!

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
5
  • Well haven't thought of that case yet, but this shouldn't block any ping requests from the host right?
    – Bad_Panda
    Feb 24 at 18:26
  • @A.B updated the post
    – Bad_Panda
    Feb 24 at 18:32
  • Hum I'm sorry I asked all of this, because it's probably not related to Docker. it's probably because you didn't allow traffic on the lo interface. Can't tell because I don't know where is your DNS server. I'll leave this to someone else. If you figure it out, don't hesitate to answer your own question.
    – A.B
    Feb 24 at 18:36
  • Well I'll still try an answer.
    – A.B
    Feb 24 at 18:39
  • 3
    Just an aside, but you probably should be using DROP instead of REJECT for your catch-all final rule in the INPUT chain. REJECT generates additional network traffic, which means that it can potentially be abused by people external to your system in various ways. If you truly need to reject certain traffic for some reason (say, TCP traffic to port 113), you should have rules for those specific cases, and then drop everything else. Feb 25 at 2:56

1 Answer 1

5

The added iptables rules prevent the system to access itself for its own services. If the DNS server is running on the system and queried using the host's main address or 127.0.0.1 then it can't be reached anymore from the system to itself. Fix this by inserting a rule to allow such access with:

iptables -I INPUT -i lo -j ACCEPT

When configuring, just put this rule first (and then you can use -A instead of -I).


In addition, because of the REJECT rule and its possible unexpected effects described in (recent enough) iptables-extensions(8):

Warning: You should not indiscriminately apply the REJECT target to packets whose connection state is classified as INVALID; instead, you should only DROP these.

[skipping detailed explanation about delayed retransmitted TCP packets triggering a bug-like behavior]

this can make legitimate (usually long-lived) TCP connections unexpectedly terminated.

At least with kernels before 6.1, the following should be used if the REJECT rule is kept and not itself changed into DROP (for improved security, as already commented):

-I INPUT -m conntrack --ctstate INVALID -j DROP

It can be put anywhere, as long as it's before the REJECT rule.

8
  • Yeah that fixes it. Although it is interesting that lo interface access is needed for DNS, I was in assumption a publicly available DNS server would be called to fetch the DNS records.
    – Bad_Panda
    Feb 24 at 19:02
  • 3
    @Bad_Panda Many (most?) distros are set up to use a local caching resolver to handle DNS lookups, in almost all cases by having it listen on the loopback interface, and having everything else on the system pointed at that as the primary DNS server. This usually just forwards the request to an upstream server, but having it (and using it) significantly reduces the need for external DNS traffic with most typical DNS usage patterns. Feb 25 at 2:50
  • 2
    @Bad_Panda That said, you are not improving security by blocking traffic on the loopback interface (anybody who can send packets there already has the ability to run arbitrary code on your system, so they can cause plenty of other issues without needing it), and it is very very likely to break things other than DNS eventually, so you probably should just keep the rule to allow traffic on the loopback interface. Feb 25 at 2:52
  • 2
    @Bad_Panda: Ubuntu uses SystemD-ResolveD for DNS resolution. SystemD-ResolveD is designed for highly-dynamic networking environment such as cloud VMs being live-migrated between servers, mobile devices changing WiFi networks on the fly, or changing between WiFi and mobile, laptops being plugged and unplugged, laptops being put to sleep in one environment and waking up in a completely different one. Therefore, Ubuntu does not use a static name server in /etc/resolv.conf by default. For applications that bypass standard Unix name resolution and read /etc/resolv.con directly, SystemD-ResolveD Feb 25 at 11:32
  • 2
    … runs a "proxy" nameserver on 127.0.0.53 and puts that address into /etc/resolv.conf. That way, even applications that bypass SystemD-ResolveD or NSS and read /etc/resolv.conf directly are guaranteed to resolve addresses the same way as applications that use NSS or use SystemD-ResolveD directly. Whether you want and/or need that, is a different question. By default, /etc/resolv.conf is a symlink to /run/systemd/resolve/stub-resolv.conf, which is dynamically updated by SystemD-ResolveD. Feb 25 at 11:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .