RaspberryPi/July 2020
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
Wifi
Set up wpa supplicant config file for your local wifi network
https://charlesreid1.com/wiki/Ubuntu/Bespin#Configure_WPA_Supplicant
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
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
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.
Thing 1
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 enable openvpn@${PROFILE}
systemctl start openvpn@${PROFILE}
Verify it is working:
curl -4 icanhazip.org
and verify it is working.
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
eth0connected to a network at192.168.0.0/24 - The hostapd wifi network is provided through a wifi card
wlan0and providing a network at192.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
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.
Start hostapd service
The service has to be unmasked before it can be started:
sudo systemctl unmask hostapd sudo systemctl enable hostapd sudo systemctl start hostapd
Modifying 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
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
Set Preferred DNS Nameservers for Thing 1
NOTE: THIS WHOLE SECTION IS NOT EVEN NEEDED - WE HAVE DISABLED SYSTEMD-RESOLVED
(Following instructions from RaspberryPi/Hotspot)
Remove the existing file at /etc/resolv.conf (a symlink to a network manager thing). Create a new version of the file that specifies preferred nameservers.
NOTE: This is different from the DNS server set in the dnsmasq config file above. That DNS address specifies where to send DNS queries from clients on the network. The instructions below cover how to change the DNS server used for local DNS queries.
If the PiHole is not set up, can use a public DNS service,
/etc/resolv.conf
nameserver 8.8.8.8
but preferably we can use the IP for the PiHole DNS service run by Thing 2, so that users have an additional layer of security.
/etc/resolv.conf
nameserver 192.168.0.300
NOTE: this file will be overwritten at boot by Network Manager. If your DNS is broken and dnsmasq does not seem to be able to find a preferred nameserver, circle back and double-check that network manager has been disabled.
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
Connecting Hostapd and PIA
To continue on the description of the setup provided above, this section describes how to achieve the following setup:
- The main internet connection for the Pi is a physical ethernet cable
eth0connected to a network at192.168.0.0/24 - The hostapd wifi network is provided through a wifi card
wlan0and providing a network at192.168.10.0/24 - The Pi runs a VPN tunnel to a PIA server, which creates the virtual device
tun0 - Traffic from the hostapd wifi network
wlan0is tunneled through the PIA tunneltun0 - NO traffic passes directly between
wlan0andeth0
To connect the hostapd network to the PIA tunnel, we need to use iptables to forward packets from one network interface to another.
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.
To use the PiHole DNS as the system DNS, edit the following file:
/etc/resolv.conf
nameserver 192.168.0.300
(replace 300 with the ip of the pihole server)
Now restart the resolved service:
sudo systemctl restart systemd-resolvd
Now you can check to verify that dig returns the right IP (0.0.0.0) for doubleclick.net:
dig doubleclick.net
This file /etc/resolv.conf SHOULD be persistent across reboots, but double-check.
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 INPUT ACCEPT
$ipt -P FORWARD ACCEPT
$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).
Related Pages
Flags