Raspberry Pi Backup

raspberry-pi-sd-backup-cards

So, now the “piwall” has been up and running for a while and I’ve done some changes to the config and the system since the last blog post. But what if the Pi decides to eat the SD card or I get hacked or… Oh, I need a backup.

There’s a number of backup solutions to choose among, and I decided to go with an easy one: to clone the whole system – as is – which resides on a 16GB SD card. I tried different ways of doing the cloning and ended up using the command line tool “dd” to accomplish the task.

On a mac, you can use the diskutil program to list the mounted disks:

$ diskutil list
...
/dev/disk3
#: TYPE NAME SIZE IDENTIFIER
0: FDisk_partition_scheme *15.9 GB disk3
1: DOS_FAT_32 NAMNLOS 15.9 GB disk3s1

In order for dd to work, unmount any partitions on the SD card:

diskutil unmountDisk /dev/diskN

“dd” will perform a block-by-block copy the contents of the SD card into a file. This command will take some time (on my 16GB RAM i7 Mac Book Pro it takes a couple of hours) and there will be no feedback during the process. Adding the “bs” argument may speed up the process.

sudo dd if=/dev/diskN of=/path/to/backup.img bs=1m

Copying the img-file onto a new SD card is a matter of simply reversing the arguments. Just remember to unmount partions as described above on the destination card.

sudo dd of=/dev/diskN if=/path/to/backup.img bs=1m

Update: Using /dev/rdisk instead of /dev/disk may be faster on the mac (source).

Advertisements

Raspberry Pi vlan Routing

gs108t

(Update: this is probably not a 100% safe setup and the PI’s 10 Mb/s network interface limitation makes this solution somewhat limited. But it was a fun exercise ;-))

I wanted to expand my home network beyond Apple Airport’s three LAN ports, into three separate networks: a Internet-of-Things network, where my TellstickNet could live; a demilitarized zone where I could put a web server without worrying too much; and a local area network where my files would be safe. To get this I thought I needed a firewall with three network interfaces plus switches for the three networks.

I happened to mention my plans to my colleague and network expert Tobias Genberg. He said something like this:

“You have a Raspberry Pi, right?”

“Yes…”

It turned out my plan was needlessly complicated and expensive. What I could do instead was to get a “smart switch”, a switch capable of running virtual networks, and then use my Raspberry Pi as a firewall slash router. I decided to proceed with this solution.

I knew this was going to be a challenge, because I had to learn a lot – how to configure the switch; how to setup networking on the Pi with virtual interfaces, vlans, dhcp, and dns; learn to understand how iptables works. And of course, I did not know what I did not know when I started. I put a lot of hours into this project, and while my friends and family suffered, I learned a few things about networking and Linux.

Switch configuration

There are a lot of switches out there. I fell for the Netgear GS108T v2 – a capable and yet affordable piece of switch. It is made out of metal and is quite heavy for its small size. A solid impression.

A Virtual LAN (VLAN) is a group of devices on one or more LANs that are configured so that they can communicate as if they were attached to the same wire, when in fact they are located on a number of different LAN segments. Because VLANs are based on logical instead of physical connections.

On this switch, vlan numbers can be any number between 1-4093, except vlan 1-3 which are reserved. I came up with a naming scheme that includes the port numbers, so WAN on port 1 becomes 11 and LAN on port 2 and 3 becomes 23. Easy to remember.

  • 11 WAN – the Internet connection
  • 23 LAN
  • 45 IOT – Internet of Things
  • 66 DMZ

WAN cable goes into port 1 and Pi router connects to port 8.

A vlans on the GS108T have untagged and tagged ports. Devices connected to an untagged ports will not notice that they are indeed on a vlan and will have the same experience as when connecting to a “normal” network. The tagged port however is where the vlan magic happens. The tagged port 8 will enable the router to distinguish between several logical networks on the same physical port.

vlan membership

The table below illustrates how ports on each vlan are configured.

1 2 3 4 5 6 7 8
vlan 11 U T
vlan 23 U U T
vlan 45 U U T
vlan 66 U T

Each port are assigned a default vlan.

pvid configuration

Ingress Filtering enabled on all ports except router port 8 (picture is not showing this). To my understanding, when enabled, ethernet frames from other vlans are discarded, which seems like a good thing. When disabled, all frames are forwarded, essential for the vlan routing to work.

Router Prerequisites

I decided to run the Pi on Raspian using NOOBS to install it. A small but very important detail: ip forwarding must be enabled for all this to work (I learned this the hard way)!

sudo echo 1 >> /proc/sys/net/ipv4/ip_forward

Uncomment the line below in /etc/sysctl.conf to enable packet forwarding for IPv4.

net.ipv4.ip_forward=1

vlan

Raspian does not come with vlan out of the box, so the vlan package has to be installed:

apt-get install vlan

The 8021q kernel module has to be loaded

echo 8021q >> /etc/modules

If everything works …

lsmod | grep 8021q

… should output something like this:

8021q                  18046  0 
garp                    6335  1 8021q

DHCP

We need to install a dhcp server, I choose to run isc-dhcp-server.

apt-get install isc-dhcp-server

There’s a few tools that are very useful when debugging network issues.

apt-get install tcpdump

Vconfig

Adding vlans to the router is done with the vconfig command. There are different naming conventions for vlans. I choose to use the interface.vlan-number convention, e.g eth0.11, which I think is the default one. But to be sure, just run:

vconfig set_name_type DEV_PLUS_VID_NO_PAD

Adding the vlans:

vconfig add eth0 11
vconfig add eth0 23
vconfig add eth0 45
vconfig add eth0 66

Interface Definitions

auto lo

iface lo inet loopback

# eth0 is not used
auto eth0
iface eth0 inet static
	address 0.0.0.0
	netmask 255.255.255.255

# WAN
auto eth0.11
iface eth0.11 inet dhcp
	vlan_raw_device eth0

# LAN
auto eth0.23
iface eth0.23 inet static
	address 192.168.23.1
	netmask 255.255.255.0
	mtu 1500
	vlan_raw_device eth0

# IOT
auto eth0.45
iface eth0.45 inet static
	address 192.168.45.1
	netmask 255.255.255.0
	mtu 1500
	vlan_raw_device eth0

# DMZ
auto eth0.66
iface eth0.66 inet static
	address 192.168.66.1
	netmask 255.255.255.0
	mtu 1500
	vlan_raw_device eth0

# Extra
auto eth0.77
iface eth0.77 inet static
	address 192.168.77.1
	netmask 255.255.255.0
	mtu 1500
	vlan_raw_device eth0

iface default inet dhcp

DHCP Configuration

ddns-update-style none;
ddns-domainname "home.local";
ignore client-updates;

# option definitions common to all supported networks...
option domain-name "home.local";
option domain-name-servers 192.168.23.1, 192.168.45.1, 192.168.66.1;

default-lease-time 600;
max-lease-time 7200;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;

# LAN
subnet 192.168.23.0 netmask 255.255.255.0 {
  range 192.168.23.10 192.168.23.30;
  option routers 192.168.23.1;
  option broadcast-address 192.168.23.255;
  option domain-name "lan.home.local";
}

# IOT
subnet 192.168.45.0 netmask 255.255.255.0 {
  range 192.168.45.10 192.168.45.30;
  option routers 192.168.45.1;
  option broadcast-address 192.168.45.255;
  option domain-name "local";
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}

# DMZ
ddns-update-style none;
ddns-domainname "home.local";
ignore client-updates;

# option definitions common to all supported networks...
option domain-name "home.local";
option domain-name-servers 192.168.23.1, 192.168.45.1, 192.168.66.1;

default-lease-time 600;
max-lease-time 7200;

# If this DHCP server is the official DHCP server for the local
# network, the authoritative directive should be uncommented.
authoritative;

# Use this to send dhcp log messages to a different log file (you also
# have to hack syslog.conf to complete the redirection).
log-facility local7;

# LAN
subnet 192.168.23.0 netmask 255.255.255.0 {
  range 192.168.23.10 192.168.23.30;
  option routers 192.168.23.1;
  option broadcast-address 192.168.23.255;
  option domain-name "lan.home.local";
}

# IOT
subnet 192.168.45.0 netmask 255.255.255.0 {
  range 192.168.45.10 192.168.45.30;
  option routers 192.168.45.1;
  option broadcast-address 192.168.45.255;
  option domain-name "local";
  option domain-name-servers 8.8.8.8, 8.8.4.4;
}

# DMZ
subnet 192.168.66.0 netmask 255.255.255.0 {
  range 192.168.66.10 192.168.66.30;
  option routers 192.168.66.1;
  option broadcast-address 192.168.66.255;
  option domain-name "dmz.home.local";
}

Iptables

Iptables is a tool for manipulating, filtering, redirecting, and blocking network traffic rules on Linux, which forms the foundation of the firewall functionality in this setup.

I put all the iptables rules in a script to make it all more manageable.

#!/bin/sh

WAN=eth0.11
LAN=eth0.23
IOT=eth0.45
DMZ=eth0.66

NET_RANGE=192.168.0.0/16

WAN_NET=192.168.11.0/24
LAN_NET=192.168.23.0/24
IOT_NET=192.168.45.0/24
DMZ_NET=192.168.66.0/24

# Delete existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

## General rules
# -P option describes the default policy for these chains
# Filters packets destined to the firewall. 
iptables -P INPUT DROP

# Filters packets to servers accessible by another NIC on the firewall. 
iptables -P FORWARD DROP

# Filters packets originating from the firewall 
iptables -P OUTPUT ACCEPT


## ICMP
# Accept icmp but limit them to 2/s on the outside
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 2/s -i $WAN -j ACCEPT
# Set no limits on other interfaces
iptables -A OUTPUT -p icmp --icmp-type echo-request ! -i $WAN  -j ACCEPT
iptables -A INPUT  -p icmp --icmp-type echo-reply ! -i $WAN  -j ACCEPT


# Defense for SYN flood attacks by limiting the acceptance of TCP segments 
# with the SYN bit set to no more than five per second
iptables -A INPUT -p tcp --syn -m limit --limit 5/s -i $WAN -j ACCEPT


# Allow loopback access
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A INPUT -s 127.0.0.1/32 -j ACCEPT


## ssh
# Allow ssh on all interfaces - a good password, fail2ban, 
# and two factor authentication will hopefpull keep us safe
iptables -A INPUT -p tcp -m multiport --dports 22 -j ACCEPT


## WAN
# NAT
iptables -A POSTROUTING -t nat -o $WAN -s $NET_RANGE ! -d $NET_RANGE  -j MASQUERADE
# Drop Private Network Address On Public Interface
iptables -A INPUT -i $WAN -s $NET_RANGE -j DROP
# Prior to masquerading, the packets are routed via the filter
# table's FORWARD chain.
# Allowed outbound: New, established and related connections
# Allowed inbound : Established and related connections
iptables -A FORWARD -t filter -o $WAN -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -t filter -i $WAN -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT


## LAN
iptables -A INPUT -s $LAN_NET -i $LAN -j ACCEPT
# Block input from other networks
iptables -A INPUT ! -s $LAN_NET -i $LAN -j REJECT
iptables -A FORWARD -d $LAN_NET -j ACCEPT
iptables -A OUTPUT -s $LAN_NET -i $LAN -j ACCEPT


## IOT
# Only accept access from LAN
iptables -A INPUT -s $LAN_NET -d $IOT_NET -j ACCEPT
# Reject others
iptables -A INPUT -s $LAN_NET ! -d $IOT_NET -j REJECT
iptables -A FORWARD -d $IOT_NET -j ACCEPT
iptables -A OUTPUT -s $IOT_NET -i $IOT -j ACCEPT


## DMZ
iptables -A INPUT -s $DMZ_NET -j ACCEPT
# Block DMZ from doing outward connections
iptables -A OUTPUT -s $DMZ_NET -j REJECT

iptables-save 
 

… and then I made another script which wipes all rules. Believe me, it can be very useful. Iptables is not too hard to understand, but when you don’t, you often find yourself locked out.

#!/bin/sh

iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

iptables-save
iptables -L

Conclusions

I’ve been running this setup for a couple of weeks now without (knowingly) being hacked. If you see places for improvements, I would like to hear about them.

Thank you Tobias for helping me out 😉