From charlesreid1

We give a walkthru of the current iptables, then cover some improvements we can make.

Existing Iptables Rules

We walk through each step of the existing iptables script.

Env Var Alias

Start by defining ipt as an alias for the iptables command:

#!/bin/bash
set -e

ipt="sudo /sbin/iptables"

Flush Existing Rules

We flush all the rules from iptables before we start:

# start by flushing all rules and setting defaults
$ipt -F
$ipt -P INPUT ACCEPT
$ipt -P FORWARD ACCEPT
$ipt -P OUTPUT ACCEPT
$ipt -t nat -F
$ipt -t mangle -F
$ipt -F
$ipt -X

Rules for PIA VPN Tunnels

We set up iptables rules that accept traffic coming in from the tunnel, and allow traffic from other interfaces and other networks to leave the tunnel (via nat/masquerading):

##################################
# PIA VPN Tunnels

# These are PIA tunnels that handle traffic from APs
PIA_AP_TUNNELS="tun1"
for TUN in TUNNELS; do
    # Accept all traffic coming in from tunnel
    $ipt -A INPUT -i ${TUN} -j ACCEPT
    # Masquaerade outgoing traffic leaving via the tunnel
    $ipt -t nat -A POSTROUTING -o ${TUN} -j MASQUERADE
done

AP-PIA Tunneling

Next we cover the rules that allow traffic to be forwarded from the AP to the VPN tunnel and to return back to the AP.

##################################
# AP-PIA Tunneling

# Forward outgoing traffic for APs through tunnel
AP="wlan1"
TUN="tun1"
$ipt -A FORWARD -i ${AP} -o ${TUN} -j ACCEPT
$ipt -A FORWARD -i ${TUN} -o ${AP} -m state --state ESTABLISHED,RELATED -j ACCEPT

DNS

This is the section that needs extra rules if we're going to be more strict about connections allowed.

We have the local dnsmasq DNS server set up to forward DNS queries it can't resolve to the PiHole DNS server (running via docker-compose).

If we're going to enable DNS queries that the PiHole can't resolve to reach the wider internet, we need to create a rule to allow traffic from the local loopback interface (lo:1 that the PiHole is listening on, see Ubuntu/Bespin/PiHole) to egress through the VPN tunnel.

Likewise, we want to allow responses from the PiHole's queries to be able to return to the PiHole via the tunnel.

##################################
# DNS Tunneling

# Forward outgoing DNS traffic from lo:1 (PiHole) through PIA tunnel
DNS="lo:1"
TUN="tun1"
PROTOCOLS="udp tcp"
for PROTOCOL in $PROTOCOLS; do
    # PiHole can always send DNS queries out through tunnel
    $ipt -A FORWARD -p ${PROTOCOL} -i ${DNS} -o ${TUN} --dport 53 -j ACCEPT
    # Responses to PiHole can always return via tunnel
    $ipt -A FORWARD -p ${PROTOCOL} -i ${TUN} -o ${DNS} --dport 53 -m state --state ESTABLISHED,RELATED -j ACCEPT
done

Save Rules

Last, we save the rules:

# Make rules persistent
sudo netfilter-persistent save


Improvements

Strict Traffic Control

Currently, we have a big problem with our iptables configuration. It is in the form of these lines:

$ipt -P INPUT ACCEPT
$ipt -P FORWARD ACCEPT
$ipt -P OUTPUT ACCEPT

In other words, we are actually accepting all traffic! No matter what! Rules don't matter!

What we really want to do is start by denying all traffic by default, and unblocking the traffic we expect. Change these lines to:

$ipt -P INPUT DENY
$ipt -P FORWARD DENY
$ipt -P OUTPUT ACCEPT

This allows all outgoing traffic by default, but blocks all incoming and forward traffic. This is going to break a lot of things, including DNS, which gives us internet connectivity, so we need to modify our rules.

Modifications needed:

  • DNS traffic for the local DNS servers should be allowed (both coming in, from other local services querying the DNS server, and going out, in case the DNS server needs to pass a request upstream)
  • SSH and VPN traffic should be allowed (incoming: only existing connections; outgoing: any connections)
  • HTTP/HTTPS traffic should be allowed (incoming: only existing connections; outgoing: any connections) - if you don't open these ports, aptitude will have problems installing/updating things

Improving DNS Rules