This article is a continuation of Part 1
Network Layout
My Internal Network is laid out a bit like this:
Home: 10.100.0.0/16
Hosted Machines at my Colo (VPN Concentrator, web server, etc): 10.101.0.0/16
Upstate House: 10.103.0.0/16 -- I also built one of these appliances for this application.
Road Warriors (laptops, tablets, phones on VPN:) 10.102.0.0/16
My colocated machine is already running OpenBSD's Ipsec Implementation, therefore it'll act as the VPN concentrator
BIOS Configuration
These appliances use a Standard Phoenix or AMI bios, I configured the following parameters:
State After Power Failure: ON
Boot Order: Boot from mSATA
Wake on LAN: Enabled
OS Installation
I downloaded a copy of OpenBSD from a local OpenBSD mirror and popped onto a USB drive using the dd command. Note: You'll need install61.fs, not install61.iso
My USB Disk was /dev/sdd when attached to my Linux System, so as root i did the following to build the USB installer:
# dd if=/home/jason/install61.fs of=/dev/sdd bs=1M
Once that was complete, it was a fairy simple installation using the defaults and all package sets in the text mode OpenBSD installer.
I connected the WAN port to an outbound internet bound connection and configured it to utilize DHCP, this interface became known as em0
I also configured a static IP on the "internal" side just to save a minute of setting the /etc/hostname.em3 file manually. I named this interface 10.100.0.1
OS Inital Configuration
- There were a handful of inital tasks that I needed to perform after the system install.
- - Install some packages: ntopng (traffic flow analysis with a nice web UI), vim, and bash. The Upstate house also got Ubiquity's Unifi software to coordinate and control Unifi APs.
- - Configure the OS and services on boot:
-
- Enable dhcpd on boot and set it to listen on em3:
echo "dhcpd_fags=em3" >> /etc/rc.conf.local
- Enable dhcpd on boot and set it to listen on em3:
-
- Enable IKE Keying Daemon (this is required for ipsec):
echo "isakmpd_flags=-K -L" >> /etc/rc.conf.local
- Enable IKE Keying Daemon (this is required for ipsec):
-
- Ensure IPSEC is enabled :
echo "ipsec=YES" >> /etc/rc.conf.local
- Ensure IPSEC is enabled :
-
- Ensure redis and ntopng are started in the correct order:
echo "pkg_scripts=redis ntopng" >> /etc/rc.conf.local
- Ensure redis and ntopng are started in the correct order:
-
- Enable IP forwarding
echo "net.inet.ip.forwarding=1" >> /etc/sysctl.confAt this point the next steps are to configure dhcpd, reboot, then configure PF and Ipsec.
- Enable IP forwarding
Setting up Internal DHCP
Setting up dhcpd on OpenBSD is fairly straightforward:
/etc/dhcpd.conf:
subnet 10.100.0.0 netmask 255.25.0.0 {
option routers 10.100.0.1;
option domain-name servers 8.8.8.8;
range 10.100.0.70 10.100.0.200;
}
Then drop a blank file to act as the database for the dhcpd leases:
# echo > /var/db/dhcpd.leases
Then start dhcpd, grab a spare machine and connect it to the em3 interface (labeled LAN on the device)
# /etc/rc.d/dhcpd start
If that's successful, DHCP's configured and we can move forward. It's a good idea to reboot now and verify that everything comes up on boot.
PF Firewall Configuration
PF is an absolutely excellent firewall implementation, however it does handle NAT a bit different than IPTables does on Linux.
/etc/pf.conf looks like this:
First we configure a couple of variables, and tell PF to avoid filtering the local loopback connecton:
set skip on lo0
ExtIf = "em0"
IntIf = "em3"
Referring to ExtIf and IntIf as external and internal interfaces respectively makes life a bit easier later on.
Then we define what our Internal Network looks like (in this case, the second machine got a slightly different entry)
PrivNet = "10.100.0.0/16"
Now we can move on to some rules, starting with blocking everyhing inbound from the internet, and allowing traffic from the internal interface to hit the device. Note the "log" on the pass command, that will log traffic an allow us to use pflog for diagnostic purposes.
block in on em0 from any
pass in log on em0 from em3:network
Next thing we need to do is allow VPN inbound from the colocated machine. Note the "quick" on the pass, that means that if this rule matches, PF will not do any further filtering on this traffic:
pass in quick on em0 inet proto udp from vpn.colocated.machine to port {isakmp, ipsec-nat-t}
Now we need to allow traffic from the colo network
pass in on enc0
pass out on enc0
The next couple of rules configure NAT, allows APIPA for confused windows clients, and allows outbound internet for the device itself.
First APIPA:
pass in log on em0 from 169.254.0.0/16 to any
Then let's get NAT working:
pass out on em0 inet from em3:network to any nat-to em0 keep state
Now allow outbound internet from the device itself:
pass out on em0 inet from em3 to any
pass out on em0 inet from em0 to any
pass in on em0 from localhost
pass in on em0 from em3:network
We then Allow hosts on our internal network to access the firewall:
pass in on $IntIf from em3:network
We don't need to be concerned about the other ipsec VPN hosts as they'll come in via the enc0 interface which we allowed earlier.
Then we Enable SSH to a Raspberry PI I keep around just for that purpose, we configure a port forward for that:
pass in log on $ExtIf proto tcp from any to any port 22
pass in log on $ExtIf proto tcp port 22 rdr-to 10.100.0.4
Finally, we allow inbound SIP and some of the high ports it requires for VOIP to my VoIP device:
pass in on $ExtIF proto udp from any to any port { 10000:20000, 5060:5061, 5064 } rdr-to 10.100.0.3
Now that we're done with pf.conf, we load the file, and verify that a machine connected to the LAN interface can get out to the internet.
# pfctl -f /etc/pf.conf
If we've got connectivity and can get out to the web, NAT's then working, we can then move forward and configure the VPN.
IPsec Configuration
I wanted to have a static tunnel to my colocated machines network as well as the other devices on my 10.0.0.0/8 private network, so configuring IPsec on my home device was the best option.
Setting up IPsec was fairly straightforward:
First thing I did was generate a pre-shared key, a rather long and secure one that shouldn't be vulernable to a rainbow table attack:
# openssl rand -base64 128
This returns a nice big random PSK that I copied for later use. I'll call it BIGPSK going forward for simplicity.
Next thing I did was configure the ipsec.conf file on my colo machine:
ike dynamic esp transport from 10.101.0.0/16 to 10.100.0.0/16 local <my external ip> peer <my home DNS or IP> \
main auth hmac-sha2-256 enc blowfish grup modp2048 \
quick auth hmac-sha2-384 enc blowfish group modp-2048 \
psk "BIGPSK" \
tag "colo to home"
ike dynamic esp transport from 10.102.0.0/16 to 10.100.0.0/16 local <my external ip> peer <my home DNS or IP> \
main auth hmac-sha2-256 enc blowfish grup modp2048 \
quick auth hmac-sha2-384 enc blowfish group modp-2048 \
psk "BIGPSK" \
tag "home to road warriors"
ike dynamic esp transport from 10.103.0.0/16 to 10.100.0.0/16 local <my external ip> peer <my home DNS or IP> \
main auth hmac-sha2-256 enc blowfish grup modp2048 \
quick auth hmac-sha2-384 enc blowfish group modp-2048 \
psk "BIGPSK" \
tag "Upstate to home via colo
I also configured some PF rules on the colo machine to allow traffic from 10.100.0.0/16. Routing is handled by ipsec inside the OpenBSD network stack, therefore adding a static route wasn't needed.
I then configured the local firewall's /etc/ipsec.conf:
ike dynamic esp transport from 10.100.0.0/16 to 10.101.0.0/16 local <my external ip> peer <my colo ip> \
main auth hmac-sha2-256 enc blowfish grup modp2048 \
quick auth hmac-sha2-384 enc blowfish group modp-2048 \
psk "BIGPSK" \
tag "colo to home"
ike dynamic esp transport from 10.100.0.0/16 to 10.102.0.0/16 local <my external ip> peer <my colo ip> \
main auth hmac-sha2-256 enc blowfish grup modp2048 \
quick auth hmac-sha2-384 enc blowfish group modp-2048 \
psk "BIGPSK" \
tag "home to road warriors"
ike dynamic esp transport from 10.100.0.0/16 to 10.103.0.0/16 local <my external ip> peer <my colo ip> \
main auth hmac-sha2-256 enc blowfish grup modp2048 \
quick auth hmac-sha2-384 enc blowfish group modp-2048 \
psk "BIGPSK" \
tag "Upstate to home via colo
I then re-loaded ipsec.conf on both machines by issuing ipsecctl -f /etc/ipsec.conf
After waiting about 3 minutes, I verified we had Ipsec Flows and the tunnels were establishd by issuing ipsecctl -sa A quick SSH connection verified everything worked as intended.
Next Steps
After some minor troubleshooting and adjustments, I verified all traffic was being passed and devices behind the new device were happy. I then put it inline and brought it up as my home router. Whole project took about 4 hours total. VPN works nigh-flawlessly. Overall it was a fairly simple setup with only a few snags and provides a great level of functionality, speed and security.
Thank You for reading!