TommyPeanuts asked:
I have a server running Ubuntu 16.04 with an application that only needs outgoing connections for package updates and NTP time syncing. It has a dynamic IPv6 address on a separate network interface for this purpose. All other connections are via the LAN on another interface, which has no gateway to the WAN.
I’d like to secure this machine by disallowing any outgoing connections other than for package updates and NTP time syncing.
However, when I try the following rules, requests to the allowed hosts are blocked:
ip6tables -A OUTPUT -o lo -p all -j ACCEPT
ip6tables -A OUTPUT -p icmpv6 -j ACCEPT
ip6tables -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
ip6tables -A OUTPUT -p udp -m owner --uid-owner systemd-timesync -j ACCEPT
ip6tables -A OUTPUT -p tcp --dport 53 -j ACCEPT
ip6tables -A OUTPUT -p udp --dport 53 -j ACCEPT
while read p; do
ip6tables -A OUTPUT -d $p -j ACCEPT
done < firewall/hosts-to-allow.list
ip6tables -A OUTPUT -o ens18 -j REJECT
Note that incoming icmpv6 requests are allowed, but all other incoming ports are blocked.
It seems the blocked entries are for packets going to the DNS resolvers (2001:0ba8:0000:2c02::):
Mar 24 08:16:19 violet kernel: [585601.187999] IPTables-Dropped: IN= OUT=ens18 SRC=2001:0ba8:0000:2c38:2841:0fff:fe53:20eb DST=2001:0ba8:0000:2c02:0000:0000:0000:0000 LEN=98 TC=0 HOPLIMIT=64 FLOWLBL=457722 PROTO=UDP SPT=46870 DPT=53 LEN=58
I’ve tried explicitly adding the resolver addresses to the allowed hosts file in the above script, but it makes no difference.
When I tried temporarily adding a fixed IPv4 address to the WAN interface (and adding identical IPv4 rules) it does work. So I assume this is something to do with IPv6.
EDIT: Here’s the fully applied rules
Chain INPUT (policy ACCEPT 1 packets, 104 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 LOGGING all * ens18 ::/0 ::/0
0 0 ACCEPT all * lo ::/0 ::/0
0 0 ACCEPT all * ens19 ::/0 ::/0
0 0 ACCEPT icmpv6 * * ::/0 ::/0
0 0 ACCEPT icmpv6 * * ::/0 ::/0
0 0 ACCEPT all * * ::/0 ::/0 ctstate NEW,RELATED,ESTABLISHED
0 0 ACCEPT tcp * * ::/0 ::/0 tcp dpt:53
0 0 ACCEPT udp * * ::/0 ::/0 udp dpt:53
0 0 ACCEPT udp * * ::/0 ::/0 owner UID match 100
0 0 ACCEPT tcp * * ::/0 2001:67c:1560:8001::14
0 0 ACCEPT tcp * * ::/0 2001:67c:1360:8001::17
0 0 ACCEPT tcp * * ::/0 2001:67c:1360:8001::21
0 0 ACCEPT tcp * * ::/0 2001:67c:1560:8001::11
0 0 ACCEPT udp * * ::/0 2001:67c:1560:8001::14
0 0 ACCEPT udp * * ::/0 2001:67c:1360:8001::17
0 0 ACCEPT udp * * ::/0 2001:67c:1360:8001::21
0 0 ACCEPT udp * * ::/0 2001:67c:1560:8001::11
0 0 ACCEPT tcp * * ::/0 2001:67c:1562::19
0 0 ACCEPT tcp * * ::/0 2001:67c:1560:8001::14
0 0 ACCEPT tcp * * ::/0 2001:67c:1562::16
0 0 ACCEPT tcp * * ::/0 2001:67c:1360:8001::21
0 0 ACCEPT tcp * * ::/0 2001:67c:1360:8001::17
0 0 ACCEPT tcp * * ::/0 2001:67c:1560:8001::11
0 0 ACCEPT udp * * ::/0 2001:67c:1562::19
0 0 ACCEPT udp * * ::/0 2001:67c:1560:8001::14
0 0 ACCEPT udp * * ::/0 2001:67c:1562::16
0 0 ACCEPT udp * * ::/0 2001:67c:1360:8001::21
0 0 ACCEPT udp * * ::/0 2001:67c:1360:8001::17
0 0 ACCEPT udp * * ::/0 2001:67c:1560:8001::11
0 0 ACCEPT tcp * * ::/0 2001:ba8:0:2c02::
0 0 ACCEPT udp * * ::/0 2001:ba8:0:2c02::
0 0 ACCEPT tcp * * ::/0 2001:ba8:0:2c04::
0 0 ACCEPT udp * * ::/0 2001:ba8:0:2c04::
0 0 REJECT all * ens18 ::/0 ::/0 reject-with icmp6-port-unreachable
Chain LOGGING (1 references)
pkts bytes target prot opt in out source destination
0 0 LOG all * * ::/0 ::/0 limit: avg 2/min burst 5 LOG flags 0 level 4 prefix "IPTables-Dropped: "
0 0 DROP all * * ::/0 ::/0
My answer:
Your OUTPUT table immediately begins by sending all traffic for ens18 to the LOGGING table, which proceeds to log and then drop all the traffic.
Remember that iptables rules are interpreted in order. Because you have already dropped all the traffic for ens18, no other rules in OUTPUT get evaluated for that traffic.
I suspect that a logging rule should be at the end of the table, rather than at the beginning. Of course you already put a REJECT target rule there, so you should decide which one of those you want.
I also suspect you would have noticed a lot sooner if you had tried to connect to your server via IPv6 on the affected interface, as you would have immediately noticed that no traffic was flowing…
View the full question and any other answers on Server Fault.
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.