From charlesreid1

Startup

Wipe SD Cards

Wipe SD cards and install raspbian

Mount SD Cards

Mount the SD cards as a local filesystem on a Linux box

Now, if you want to modify the file /foo/bar, you can edit the file on the SD card at /media/ubuntu/rootfs/foo/bar

Enable SSH

Touch a file named ssh in the boot sector of the SD card to enable the service to start on boot:

touch /media/ubuntu/boot/ssh

NOTE: Raspberry Pi can be very flaky, sometimes this file disappears for no reason

Wifi

Set up wpa supplicant config file for your local wifi network

https://charlesreid1.com/wiki/Ubuntu/Bespin#Configure_WPA_Supplicant

/etc/wpa_supplicant/wpa_supplicant.conf

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US

network={
    ssid="YOURWIFINETWORK"
    proto=RSN
    key_mgmt=WPA-PSK
    pairwise=CCMP TKIP
    group=CCMP TKIP
    psk="YOURWIFIPASSWORD"
}

Network Interfaces

Next set up the WPA supplicant service to automatically start for our wifi device

Update the contents of your network interfaces file to look like this:

/etc/network/interfaces

source-directory /etc/network/interfaces.d

allow-hotplug lo
iface lo inet loopback

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Possibly Required - Delete Existing WPA Startup Service

This may be required, not sure. You may need to delete existing wpa supplicant startup services in either

/etc/systemd/system/multi-user.target.wants/wpa_supplicant.service

or

/lib/systemd/system/multi-user.target.wants/wpa_supplicant.service

Definitely Required - Delete dhcpcd Startup Service

The dhcpcd startup service doesn't want anything in the /etc/network/interfaces file, but we need to use that file to configure the wifi, so ditch the dhcpcd startup service by removing the file:

/etc/systemd/system/multi-user.target.wants/dhcpcd.service

Power up the Pi

Next time you boot up the Pi you should see your wifi card light blinking.

Try running an nmap scan for port 22 before and after the pi is plugged in, from another computer on the same network:

nmap -p22 192.168.0.0/24 > nmap-before

# plug in the pi, wait a few minutes

nmap -p22 192.168.0.0/24 > nmap-after

assuming your home wifi is 192.168.0.0/24.

Troubleshooting

If you need to troubleshoot, power off the Pi and re-mount the SD card on a Linux box. Check the syslog at /media/ubuntu/rootfs/var/log/syslog and see what's going on.

Stderr no such device or address

Jul 18 23:23:11 raspberrypi wpa_supplicant[418]: ctrl_iface exists and seems to be in use - cannot override it
Jul 18 23:23:11 raspberrypi wpa_supplicant[418]: Delete '/var/run/wpa_supplicant/wlan0' manually if it is not used anymore
Jul 18 23:23:11 raspberrypi wpa_supplicant[418]: Failed to initialize control interface 'DIR=/var/run/wpa_supplicant GROUP=netdev'.#012You may have another wpa_supplicant process already running or the file was#012left by an unclean termination of wpa_supplicant in which case you will need#012to manually remove this file before starting wpa_supplicant again.
Jul 18 23:23:11 raspberrypi wpa_supplicant[418]: nl80211: deinit ifname=wlan0 disabled_11b_rates=0
Jul 18 23:23:11 raspberrypi sh[404]: /etc/network/if-pre-up.d/wpasupplicant: 120: /etc/network/if-pre-up.d/wpasupplicant: cannot create /dev/stderr: No such device or address
Jul 18 23:23:11 raspberrypi sh[404]: run-parts: /etc/network/if-pre-up.d/wpasupplicant exited with return code 1
Jul 18 23:23:11 raspberrypi sh[404]: ifup: failed to bring up wlan0

Thing 1

Installing Stuff

apt-get -y install vim dnsutils tcpdump

Installing PIA on Thing 1

This sets up a VPN tunnel at tun0 that connects to a PIA VPN server.

Run these commands as sudo:

# install openvpn
apt-get -y install openvpn

# set up pia
cd /tmp
wget https://www.privateinternetaccess.com/openvpn/openvpn.zip
unzip -d openvpn openvpn.zip
cd openvpn

# pick a profile to install
mv 'US West.ovpn' 'West.ovpn'
PROFILE="West"
cp ca.rsa.2048.crt /etc/openvpn/.
cp crl.rsa.2048.pem /etc/openvpn/.
cp ${PROFILE}.ovpn /etc/openvpn/.

# set up login credentials for PIA
touch /etc/openvpn/login
echo "USERNAME" >> /etc/openvpn/login
echo "PASSWORD" >> /etc/openvpn/login
chown root:root /etc/openvpn/login
chmod 600 /etc/openvpn/login

# modify openvpn service to use .ovpn files intead of .conf files, and set absolute paths
sed -i 's+^auth-user-pass+& /etc/openvpn/login+' /etc/openvpn/${PROFILE}.ovpn
sed -i 's+^ca ca.rsa.2048.crt+& /etc/openvpn/ca.rsa.2048.crt+' /etc/openvpn/${PROFILE}.ovpn
sed -i 's+^crl-verif crl.rsa.2048.pem+& /etc/openvpn/crl.rsa.2048.pem+' /etc/openvpn/${PROFILE}.ovpn
sed -i 's+\.conf+.ovpn+' /lib/systemd/system/openvpn@.service

# start openvpn
openvpn --config /etc/openvpn/${PROFILE}.ovpn

Once you have verified it is working, cancel the openvpn process and run the openvpn service:

systemctl start openvpn@${PROFILE}

Verify it is working:

curl -4 icanhazip.org

I have had some problems when enabling the PIA VPN service and when it can't connect (usually DNS-related). DO NOT ENABLE THE PIA SERVICE until you have all your networking pieces ready to go and you can troubleshoot JUST the PIA startup service.

systemctl disable openvpn@${PROFILE}

Connect Thing 1 to internet

At this point, you will need an internet connection, plus an unoccupied wifi device.

You can leave the first wifi card alone as it is, and plug in a second wifi card (wlan1).

Or, you can connect an ethernet cable (eth0) and use wlan0 to run the hostapd.

In our scenario we have the following setup:

  • The main internet connection for the Pi is a physical ethernet cable eth0 connected to a network at 192.168.0.0/24
  • The hostapd wifi network is provided through a wifi card wlan0 and providing a network at 192.168.10.0/24

Hostapd on Thing 1

Enable Packet Forwarding on Thing 1

First allow the Pi to forward packets and act as a router by adding this line to your sysctl config:

/etc/sysctl.conf

net.ipv4.ip_forward=1

Reload the sysctl:

sudo sysctl --system

Install hostapd on Thing 1

Install hostapd:

sudo apt-get -y install hostapd

Ensure it is not enabled:

sudo systemctl disable hostapd
sudo systemctl stop hostapd

Configure hostapd on Thing 1

Configure hostapd file:

/etc/hostapd/hostapd.conf

interface=wlan0
driver=nl80211
hw_mode=g
channel=1
macaddr_acl=0
ignore_broadcast_ssid=0

# LAN10
ssid=LAN10
wpa_passphrase=YOURPASSPHRASEHERE
auth_algs=1
wpa=3
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Now set the hostapd configuration file:

/etc/default/hostapd

DAEMON_CONF="/etc/hostapd/hostapd.conf"

At this point you should be able to start hostapd with this command:

sudo hostapd /etc/hostapd/hostapd.conf

You will be able to see the wifi network, and clients will be able to authenticate, but they won't be able to join it because they won't get IP addresses.

To fix that, we need a DNS and DHCP server. We can use dnsmasq for that.

WE WILL ENABLE THE HOSTAPD SERVICE AFTER CONFIGURING DNS/DHCP.

Configuring network interfaces for hostapd Thing 1

First, you have to specify a static network setup for the wlan1 interface (the hostapd interface that will run the wifi hotspot).

Add this to the following file:

/etc/network/interfaces

allow-hotplug wlan1
iface wlan1 inet static
    address 192.168.10.1
    netmask 255.255.255.0
    gateway 192.168.10.1

This will break dhcpcd, however, which is how the Pi runs its DHCP client and gets an IP address on the local network. So, if this is the only change you make, it will break DHCP for all interfaces.

To fix this, you have to tell dhcpcd to ignore the wlan1 interface, by adding the following line to the following file:

/etc/dhcpcd.conf

denyinterfaces wlan1

dnsmasq for DHCP and DNS for Thing 1

We are going to install dnsmasq to provide a DHCP and DNS service for the AP network.

Install dnsmasq on Thing 1

Start by installing it with apt-get:

sudo apt-get -y install dnsmasq

This will try to start dnsmasq, but it will fail and print red text. This is fine - the system's built-in systemd-resolved is already listening on port 53 so we will need to disable this service. (But we need dnsmasq installed FIRST, because disabling systemd-resolved will cause DNS queries to fail, so the internet connection will break. We need dnsmasq ready to start and take over the DNS duties.)

sudo systemctl disable systemd-resolved
sudo systemctl stop systemd-resolved

Configure dnsmasq on Thing 1

Preserve the original dnsmasq config file, which has a lot of useful information:

sudo mv /etc/dnsmasq.conf{,.orig}

Now create the dnsmasq config file.

Here is an extremely barebones version:

/etc/dnsmasq.conf

interface=wlan0
dhcp-range=192.168.10.100,192.168.10.150,255.255.255.0,24h

Here is a much better version:

/etc/dnsmasq.conf

# don't send external traffic that is missing a domain
domain-needed
# don't send external traffic that has bogus private ip
bogus-priv
# set the local domain
domain=mynet
local=/mynet/
# listen on these interfaces and only these interfaces
listen-address=127.0.0.1
listen-address=192.168.10.1
bind-interfaces
# define range of IP addresses to hand out
dhcp-range=192.168.10.100,192.168.10.150,255.255.255.0,24h
# define what to do if no name resolution
no-resolv
# useful for troubleshooting:
server=8.8.8.8
# set this to the PiHole DNS server IP address
#server=192.168.0.300
# send dnsmasq logs to a single place
log-facility=/var/log/dnsmasq.log

Now we are ready to start up dnsmasq:

sudo systemctl enable dnsmasq
sudo systemctl start dnsmasq

Adjust dnsmasq startup service

Not using dhcpcd anymore

This feels asinine but I had to adjust the startup service to tell dnsmasq to start up after dhcpcd, which assigns the wireless network interface that dnsmasq serves its IP address. If dnsmasq starts first, it can't find a network interface at 192.168.10.1.

Edit the following line of the dnsmasq startup service:

/lib/systemd/system/dnsmasq.service

Change this

After=network.target

To this:

After=network.target dhcpcd5.service

Here is a one liner that makes the change:

sed -i 's/^After=network.target$/After=network.target dhcpcd5.service/' /lib/systemd/system/dnsmasq.conf

Set Preferred DNS Nameservers for Thing 1

To set the preferred DNS nameservers, edit the configuration file for dhcpcd. This file configures dhcpcd, which is what the pi uses to get an IP address. DHCP attempts to configure DNS, so if you set the DNS nameserver here, those should be set automatically as your NDS nameserver of choice.

We want to use the dnsmasq service, which is listening on 127.0.0.1 and 192.168.10.1. We can set the nameserver to 127.0.0.1 in dhcpcd configuration file to use dnsmasq as our DNS server. Add the following line:

/etc/dhcpcd.conf

static domain_name_servers=127.0.0.1

On reboot, your /etc/resolv.conf should be dynamically updated to reflect the name server you specified in dhcpcd.conf.

Improved Logging

Dnsmasq configuration file has a log-facility option to control where logs go. Add this to the config file:

log-facility=/var/log/dnsmasq.log

Troubleshooting

To troubleshoot DNS, you may find the dig utility helpful. It is part of the dnsutils package:

sudo apt-get -y install dnsutils

Testing AP

Now that we have hostapd and dnsmasq running, let's test out the wireless AP and see how it goes.

Before testing everything out, do a reboot and make sure that all services are running as expected (dnsmasq in particular) and that network interfaces are configured as expected.

To test the AP, we will run hostapd manually first. Checklist for testing if the access point works:

  • is dnsmasq service running? (Yes)
  • is hostapd service running? (No)
  • is static ip set for the wifi card creating the AP in /etc/network/interfaces? (Yes, 192.168.10.1)
  • does ifconfig show that IP? (Yes)
  • can cients see to wifi network? (Yes)
  • can clients connect to wifi network? (Yes)
  • does handshake process succeed? (Yes)
  • does client receive an IP? (Yes)
  • can client access internet? (No)

If you already have the hostapd service running and enabled, disable/stop it:

sudo systemctl disable hostapd
sudo systemctl stop hostapd

Now run hostapd manually:

sudo hostapd /etc/hostapd/hostapd.conf

To add more debug info:

sudo hostapd -d /etc/hostapd/hostapd.conf

To log it to a file,

sudo hostapd -d /etc/hostapd/hostapd.conf 2>&1 | tee hostapd.log

From a phone or another computer, connect to the wireless network and verify you get an IP in the lease range specified in the dnsmasq config file.

Starting Hostapd Automatically

Now that we have all the bits installed and tested, we can start the hostapd startup service.

We start by modifying the startup service to be more resilient.

Modifying hostapd Startup Service to Retry

The hostapd service is very fickle, failing the first time it is run but succeeding when run a few seconds later, so we can set up the hostapd service to retry 5 times, waiting 30 seconds each time.

To do that, edit the startup service file at /lib/systemd/system/hostapd.service

Add these two lines to the [Unit] section:

[Unit]
StartLimitInterval=200
StartLimitBurst=5

Add these two lines to the [Service] section:

[Service]
Restart=always
RestartSec=30

The final version of the hostapd startup service is given below:

/lib/systemd/system/hostapd.service

[Unit]
Description=Advanced IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator
After=network.target
StartLimitInterval=200
StartLimitBurst=5

[Service]
Type=forking
PIDFile=/run/hostapd.pid
EnvironmentFile=/etc/default/hostapd
ExecStart=/usr/sbin/hostapd -P /run/hostapd.pid -B $DAEMON_OPTS ${DAEMON_CONF}
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target

Reload the service if necessary:

sudo systemctl daemon-reload

Starting hostapd startup service

To start hostap in the background as a service, and enable it to start on boot, run these commands:

sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd

Test the AP

At this point you can test out the AP.

Client should get an IP address in the specified block (192.168.10.100-192.168.10.150) from the DHCP server (dnsmasq).

They should be able to ping the gateway server at 192.168.10.1.

Clients will not have external DNS working, since the Pi has not been configured to handle DNS queries.

Connecting Hostapd and PIA

To continue on the description of the setup provided above, this section describes how to achieve the following setup:

  • wlan0 provides main wifi internet connection at 192.168.0.0/24
  • wlan1 is the hostapd network, with dnsmasq handing out IPs in 192.168.10.0/24
  • tun0 is the PIA VPN tunnel
  • Traffic from hostapd wlan1 is tunneled through PIA tunnel tun0
  • no traffic passes between wlan0 and wlan1

To connect the hostapd network to the PIA tunnel, we need to use iptables to forward packets from one network interface to another.

Thing 1 Iptables

Start by installing the netfilter-persistent tool, which will make it easy to save the iptables configuration:

sudo apt-get -y install netfilter-persistent

Now here is the iptables script to set up the routing described above. Note that we are permissive with packets (accept by default) because the Pi is behind a firewall.

#!/bin/bash
set -e

ipt="sudo /sbin/iptables"

# Set default policies
$ipt -P INPUT ACCEPT
$ipt -P FORWARD ACCEPT
$ipt -P OUTPUT ACCEPT

# Flush and clear everything
$ipt -t nat -F
$ipt -t mangle -F
$ipt -F
$ipt -X

# Name of PIA VPN tunnel device
PIATUN="tun0"
# Name of loopback interface for dnsmasq DNS server
DDNS="lo"
# Name of wifi
WLAN="wlan0"
# Name of hostapd AP device
AP="wlan1"

########### INCOMING ##########
# Allow any established connection to come in or out
$ipt -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$ipt -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

########### PING ##############
# Allow incoming ping requests
$ipt -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

########### VPN ###############
# Allow incoming VPN sessions destined for 1194, new or established
$ipt -A INPUT -p udp --dport 1194 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# Allow incoming VPN traffic coming from 1194, part of established conversation
$ipt -A INPUT -p udp --sport 1194 -m conntrack --ctstate ESTABLISHED -j ACCEPT

########### DHCP ##############
# Allow any DHCP traffic to come in or out
$ipt -A INPUT  -p udp --dport 67:68 --sport 67:68 -j ACCEPT
$ipt -A OUTPUT -p udp --dport 67:68 --sport 67:68 -j ACCEPT

########### PIA VPN ##############
# Accept all traffic coming in from tunnel
$ipt -A INPUT -i ${PIATUN} -j ACCEPT
# Masquaerade outgoing traffic leaving via the tunnel
$ipt -t nat -A POSTROUTING -o ${PIATUN} -j MASQUERADE

########### DNS ###############
PROTOCOLS="tcp udp"
for prot in $PROTOCOLS; do
    # Allow incoming DNS traffic coming from 53
    $ipt -A INPUT  -p $prot --sport 53 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT
    # Allow external DNS queries from dnsmasq to be sent out via PIA tunnel
    $ipt -A FORWARD -p $prot -i ${LO} -o ${PIATUN} --dport 53 -j ACCEPT
    # Responses to DNS queries can always return via tunnel
    $ipt -A FORWARD -p $prot -i ${PIATUN} -o ${LO} --dport 53 -m state --state ESTABLISHED,RELATED -j ACCEPT
    # Allow loopback traffic
    $ipt -A FORWARD -p $prot -i ${LO} -o ${LO} -j ACCEPT
    # Allow DNS traffic to travel between AP and loopback
    $ipt -A FORWARD -p $prot -i ${AP} -o ${DDNS} --dport 53 -j ACCEPT
    $ipt -A FORWARD -p $prot -o ${AP} -i ${DDNS} --sport 53 -j ACCEPT
done

# Enable logging
$ipt -N LOGGING
$ipt -A INPUT -j LOGGING
$ipt -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "iptables dropped: " --log-level 4
$ipt -A LOGGING -j DROP

# Make rules persistent
sudo netfilter-persistent save

Also see Ubuntu/Bespin/Iptables

Thing 2

Installing PiHole on Thing 2

This one is pretty easy. The one-liner, once you've inspected the code you're about to run (OF COURSE), is:

curl -sSL https://install.pi-hole.net | sudo bash

Normally it's bad practice to pipe to sudo bash, but this time around we make an exception. Ya know. Cuz we do like we do. You don't like it, you fuck off, you hear?

Now where was I.

Enabling DNS queries from local network

To make the PiHole work for everyone on the local network, you need to enable the PiHole to respond to DNS queries from other hosts.

Boot up the Pi and go to the admin interface at 192.168.0.*/admin. Navigate to the Settings, then the DNS tab, and pick the option to respond to all queries from computers that are one hop away (local devices).

Using the PiHole DNS as the PiHole DNS

For some reason, the PiHole doesn't configure itself to use itself as its own DNS server. By default, if you run dig doubleclick.net, it will return the real IP for doubleclick.net (even though that's a domain that the PiHole will block). But if you use the loal IP address of the PiHole, dig doubleclick.net @192.168.0.300 (replace 300 with the IP of the PiHole server), it resolves to 0.0.0.0 as expected.

We can set a static DNS to use in the DHCP configuration file, since the DNS is configured by the DHCP client whenever it gets an address.

Edit the following file and add the following line:

/etc/dhcpcd.conf

static domain_name_servers=127.0.0.1

Now the PiHole should use itself for DNS queries.

Restart the dhcpcd service:

sudo systemctl daemon-reload
sudo systemctl restart dhcpcd

Now you can check to verify that dig returns the right IP (0.0.0.0) for doubleclick.net:

dig doubleclick.net

When you restart the dhcpcd service (and after you reboot), you should see 127.0.0.1 as the only entry in your /etc/resolv.conf.

Installing PIA on Thing 2

Follow the steps above to install PIA on Thing 2.

When the installation is done, you'll probably notice that DNS is borked on the PiHole. You can fix this by TEMPORARILY disabling and stopping the PIA openvpn service, which is interfering with DNS queries:

sudo systemctl stop openvpn@${PROFILE}
sudo systemctl disable openvpn@${PROFILE}

The reason DNS is borked is, PIA blocks DNS requests so that you won't suffer from DNS leaks (where your computer is sending all its traffic through the VPN tunnel, but sending DNS requests in the clear).

The actual fix requires writing some iptables rules so that DNS requests from the PiHole at local interface lo will be directed through the PIA VPN tunnel at interface tun0, and therefore will not be blocked by PIA, but will be sent through the PIA tunnel.

Connecting PiHole to PIA

In this section we cover how to set up the PiHole on Thing 2 to send all DNS requests through the PIA tunnel.

This is gonna require a long script that sets various iptables rules for directing traffic on the machine.

As mentioned above, we need to use iptables to forward packets from one interface to another so that DNS requests can flow from clients to the PiHole server, and from the PiHole server out through the PIA tunnel to the wider internet.

The basic idea behind the rules is to specify when packets can be shared between network interfaces. For example, a packet leaving the PiHole and destined for port 53 should be shared with the VPN tunnel, so the VPN tunnel can send the traffic out.

Thing 2 make iptables persistent

To make iptables rules persistent through reboots, we will use a tool called netfilter-persistent:

sudo apt-get -y install netfilter-persistent

Thing 2 PiHole iptables setup

The iptables setup script should redirect DNS traffic in the desired way.

Summary of key rules:

  • Allow all established connections
  • Allow incoming ping and ssh connections
  • Allow traffic coming from the local wireless network
  • Allow incoming localhost traffic
  • Allow incoming PIA tunnel traffic
  • Masquerade traffic leaving the PIA tunnel
  • Allow port 53 (DNS traffic) to come in from anywhere
  • Allow PiHole to send DNS queries out through tunnel, and accept responses

Note that the PiHole settings page allows the PiHole to receive DNS queries from the local wireless network already, so no iptables rules are needed for that.

Now the script.

Thing 2 PiHole iptables script

This can go in your home directory or wherever. Run it as root!

iptables_thing2.sh

#!/bin/bash
# iptables setup for thing 2 raspberry pi
set -e

ipt="sudo /sbin/iptables"

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

# Name of PIA VPN tunnel device
PIATUN="tun0"
# Name of loopback interface for PiHole DNS server
PHDNS="lo"
# Name of wifi interface 192.168.0.0/24
WLAN="wlan0"

##################
# Incoming

# Allow any established connection to come in or out
$ipt -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
$ipt -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

#################
# Ping

# Allow incoming ping requests
$ipt -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

#################
# ssh

# Allow incoming SSH sessions, new or established
$ipt -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
# Allow incoming SSH traffic, if part of established conversation
$ipt -A INPUT -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT

#########################
# traffic from wlan

# Allow incoming (any) traffic from the wlan
$ipt -A INPUT -i ${WLAN} -j ACCEPT

#########################
# localhost to localhost
$ipt -A INPUT -i lo -j ACCEPT

##################
# pia vpn

# This is a PIA VPN tunnel that handles outbound DNS queries
# Accept all traffic coming in from tunnel
$ipt -A INPUT -i ${PIATUN} -j ACCEPT
# Masquaerade outgoing traffic leaving via the tunnel
$ipt -t nat -A POSTROUTING -o ${PIATUN} -j MASQUERADE

##################
# DNS

PROTOCOLS="tcp udp"
for prot in $PROTOCOLS; do

    # General DNS Traffic:

    # Allow incoming DNS traffic coming from 53, part of established conversation
    $ipt -A INPUT  -p $prot --sport 53 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT

    # PiHole DNS (lo) <-> PIA VPN Tunnel (tun0):

    # PiHole can always send DNS queries out through tunnel
    $ipt -A FORWARD -p $prot -i ${PHDNS} -o ${PIATUN} --dport 53 -j ACCEPT
    # Responses to PiHole can always return via tunnel
    $ipt -A FORWARD -p $prot -i ${PIATUN} -o ${PHDNS} --dport 53 -m state --state ESTABLISHED,RELATED -j ACCEPT

    # Local wifi network can already talk to pihole DNS
    # (set in pihole settings)

done


# Enable logging
$ipt -N LOGGING
$ipt -A INPUT -j LOGGING
$ipt -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "iptables dropped: " --log-level 4
$ipt -A LOGGING -j DROP

# Make rules persistent
sudo netfilter-persistent save

Testing Thing 2 iptables setup

Because we turned on monitoring, you can tail the syslog file while doing these experiments to see what packets are blocked and figure out what rules are needed to allow them:

sudo tail -f /var/log/syslog

You can also run tcpdump on a specific port to check if packets are showing up on the right network interfaces. For example, this listens on the wlan0 interface for traffic on port 53:

sudo tcpdump -i wlan0 port 53

Try a local dig from the PiHole server of a blocked domain:

dig doubleclick.net

should return 0.0.0.0

Try a local dig from the PiHole server of an unblocked domain:

dig reddit.com

Try a dig from another computer on the network pointing to the PiHole server as the DNS server:

dig npr.org 192.168.0.300

(replace 300 with the IP of the PiHole).

Secure Thing 2

Last but not least: secure the Pi!

  • Change default password if you haven't already
  • Better yet, set up passwordless SSH key login
  • Set a (different) password on the PiHole interface
  • Change the PiHole settings to anonymize data recorded by the Pi
  • Turn off DNS request logging

Related Pages

RaspberryPi

RaspberryPi/Headless

Flags