0

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, nothing is being 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.

Note that in a previous state of this question, I'd erroneously dropped all packets first after logging them.


The applied rules are as follows:

Chain INPUT (policy ACCEPT 70 packets, 126K 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 ACCEPT     all      *      lo      ::/0                 ::/0                
    8   536 ACCEPT     icmpv6    *      *       ::/0                 ::/0                
   67  6405 ACCEPT     all      *      *       ::/0                 ::/0                 state 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 REJECT     all      *      ens18   ::/0                 ::/0                 reject-with icmp6-port-unreachable

Chain LOGGING (0 references)
 pkts bytes target     prot opt in     out     source               destination  
3
  • The shell script you posted does not reflect the actual firewall rules in use on your system. Please show the actual firewall, e.g. with ip6tables -nvL Mar 24, 2019 at 15:23
  • @MichaelHampton OK thanks, I've done that. Mar 24, 2019 at 16:38
  • 1
    You're just logging and dropping ALL output traffic! Mar 24, 2019 at 16:44

1 Answer 1

0

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...


Further, after you fix that problem, you are actually explicitly allowing all traffic in this rule:

ip6tables -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT

That matches every possible valid connection state. I expect you do not want to allow all NEW connections, just those RELATED and ESTABLISHED to those you allow later.

You need to remove NEW from this (and use -m conntrack instead of the deprecated -m state) and add it to the outbound connections you want to allow, e.g.:

ip6tables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

and

        ip6tables -A OUTPUT -m conntrack --ctstate NEW -d $p -j ACCEPT
3
  • I see. I had the logging in there as part of my troubleshooting efforts when I did the ip6tables-save. I've removed the logging, but now the rules aren't blocking anything. I'll update the question. Mar 24, 2019 at 18:07
  • @TommyPeanuts I've also updated my answer based on your changes. Mar 24, 2019 at 18:34
  • Great! That now works, but it's coming up with "Bad argument `ACCEPT'" when I run the script. Stepping through it manually doesn't give me that though so I'm not sure what's up. But main issue is solved. Mar 24, 2019 at 18:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.