Category Archives: Networking

Site to Site VPN between OPNsense & OpenWRT with Tinc

I’m a real glutton for punishment. I decided to upgrade my parents’ router to OpenWRT. The upgrade went smoothly except for one thing: The VPN I had established between my firewall and theirs.

This was a big enough headache that I even ended up switching my firewall from pfSense to OPNsense (Something I had been contemplating doing for a while anyway) hoping it would make things easier. It didn’t. In the end I abandoned OpenVPN entirely and instead went with Tinc.

Tinc is cool because it’s full mesh peer-to-peer instead of the traditional client / server model. If your equipment supports it, I’d definitely choose it over OpenVPN, especially if multiple sites are involved. A basic rundown of its configuration can be found here.

I used this site as a reference for how to set up tinc.  Essentially you decide on a network name, create private & public keys for each host, and configure each host to connect to each other via a config file & folder structure.

Tinc general configuration

On each device create an /etc/tinc/<network name>/hosts directory structure

mkdir -p /etc/tinc/<network name>/hosts
tincd -n <network name> -K 4096

To configure TINC we need some additional configuration files inside the /etc/tinc/<network name> directory

  • tinc.conf
  • tinc-up (script for bringing up the interface)
  • hosts/<hostname> (one for each location)

tinc.conf can be as simple as this:

Name = <name of host>
ConnectTo = <name of other host> 
#Add each host with an additional ConnectTo line

There needs to be a corresponding file in the hosts directory for each host. Example host file:

Address = <External IP of host>
Subnet = <Subnet other host will share>
#Add more subnets with additional Subnet lines

The host file also need’s the host’s public key. Append it to the end of the file:

cat /etc/tinc/<network name>/rsa_key.pub >> /etc/tinc/<network name>/hosts/<host name>

It’s easiest to generate the host files on each respective host, then copy them to all the other hosts.

The last step is to create the tinc-up script

#!/bin/sh

ip link set $INTERFACE up
ip addr add 172.16.0.1/24 dev $INTERFACE

Modify the IP used on each host so they don’t overlap. The private network here is what’s used for inter-host communication.

Make the script executable:

chmod 755 /etc/tinc/<network name>/tinc-up

OPNSense specific configuration

I got this working through an enhanced tinc package for OPNsense located here.  I will copypasta the content from that site here for easier reference:

Installation

The version might change, adjust it if fetch fails

fetch https://raw.githubusercontent.com/EugenMayer/tinc-opnsense/master/dist/os-tincdcustom-latest.txz
pkg install os-tincdcustom-latest.txz

1. your network

  1. copy the /usr/local/etc/tinc/example folder to /usr/local/etc/tinc/yournetwork
  2. enter yournetwork into /usr/local/etc/tinc/nets.boot to let this network be started on boot
  3. create keypairs by runng tincd -n <yournetwork> -K

2. your network configuration and tun device

  1. Edit /usr/local/etc/tinc/yournetwork/tinc.conf set the server you want to connect to and how this server is to be named
  2. Edit /usr/local/etc/tinc/yournetwork/tinc-up and adjust the network/netbitmask

3. finally the host configuration

  1. enter the /usr/local/etc/tinc/yournetwork/hosts folder and rename the files according to what you have chosen for youservername and theotherservername – they must match!
  2. enter the public key of the “this server” you find under /usr/local/etc/tinc/yournetwork/ into the according thisservernamefile and adjust the subnet this server offers (or subnets)
  3. enter the public key of the “other server” into the according theotherservername file and adjust the subnet the other server offers (or subnets)

4. OPNsense Interface/Gateway/Route/FW configuration

Please see this answer for a brief description

  • You need to create a Gateway, which is configured to go through tinc0 with “dynamic” (do not enter an IP on Gateway field)
  • You need to add a route to <remote subnet> through this gateway
  • Add your tinc0 interface in the Interface section. You can configure a ipv4 address or you don’t, does not matter. If you do, use your tinc-up configured address. Doing this enabled you to create FW Rules for the Tinc interface – which we will need.
  • Add a firewall on the Tinc interface to allow communication to local & remote subnets
    • Alternatively, add a single rule for the Tinc interface to allow any/any access (lazy, less secure)
  • Don’t forget to create a firewall rule allowing the port you’ve configured tinc to run on access from the internet.

OpenWRT specific configuration

Openwrt follows the general tinc configuration exactly. Make the appropriate folders and config files in /etc/tinc/<network name>/ and then test your configuration:

tincd -n <network name>

Once connection is established and working:

Create interface for your VPN (network / interfaces / add new interface) Select the name of your tinc network name from the list.

Next bridge your VPN to the LAN by going to Network / Firewall and editing your LAN zone. Select your VPN interface created earlier from the list and hit save & apply.

Run on startup

I could not find clear documentation on getting this to work on startup. There is a startup script for tinc but it doesn’t appear to launch my tinc config. I ended up modifying /etc/init.d/tinc and adding these lines to the start() and stop() functions. You could also just write your own simple init script to accomplish this.

start() {
...
/usr/sbin/tincd -n <network name>
}

stop() {
...
kill `pidof tincd`
}

Troubleshooting

Tincdcustom service won’t start in OPNSense

Starting from the GUI just does nothing, starting from CLI reveals this unhelpful error:

configctl tincdcustom status

Error (1)

From the OPNSense docs I determined which command I can run to see exactly why. The command is located in this configd configuration file: /usr/local/opnsense/service/conf/actions.d/actions_tincdcustom.conf

command:/usr/local/etc/rc.d/tincdcustom start

Doing that command manually revealed what the problem was:

/usr/local/etc/rc.d/tincdcustom start

Please create /usr/local/etc/tinc/nets.boot.

I had skipped step 1.2 of the tincdcustom instalaltion guide:

enter yournetwork into /usr/local/etc/tinc/nets.boot to let this network be started on boot

Once I added a single word – the name of the network I want to start on bootup – to /usr/local/etc/tinc/nets.boot – the daemon started and worked properly.

Running Tinc in verbose mode

Coming from the tinc documentation, I ran tinc in verbose mode on both of my hosts to troubleshoot why a connection wasn’t happening. It was very helpful.

tincd -n netname -d5 -D

Fix no internet in pfSense OpenVPN

I came across an issue with pfSense where I had created an openVPN connection but it would not work with internet traffic. The VPN connection established fine and I could connect to all internal hosts, but all internet traffic simply didn’t work. I checked the firewall logs and there were no firewall denies.

After scratching my head for a while I came across this post which suggests it might be due to the fact that there was no outbound NAT defined for the VPN network I created.

I went to Firewall / NAT / Outbound and sure enough, there was no outbound NAT rule for my VPN network. I manually created it for my VPN network and voila! Internet over the VPN!

Fix pfSense OpenVPN unable to bind to VIP issue

A while ago I bought multiple static IP addresses from my ISP. I configured the IPs as Virtual IP addresses through Firewall / Virtual IPs. Everything was dandy.. until I tried to assign OpenVPN to listen on one of my new IP addresses. No matter what I tried I could only get it to work if it listened on my gateway IP.. none of my other static IP addresses would work. The GUI would let me save the configuration, but if I headed over to Status / Openvpn I would see the following:

[error] Unable to contact daemon Service not running?

Digging further in the logs by going to Status / System Logs and then selecting the OpenVPN tab revealed the following snippet:

Time Process PID Message
May 15 19:42:00 openvpn 73195 Exiting due to fatal error
May 15 19:42:00 openvpn 73195 TCP/UDP: Socket bind failed on local address [AF_INET]<redacted>:443: Can’t assign requested address

After much digging I finally stumbled upon this post in the pfsense threads. In it they mention that in the Firewall / Virtual IPs screen not to bind  (in the interface option) your IP addresses to the WAN interface, but rather to bind them to localhost. That did the trick!

Site to site VPN between pfSense and DD-WRT

I’ve been trying to establish a site-to-site VPN connection between my house and my parents’ for a couple years now. Each time I try I become frustrated and eventually give up. No longer! I’ve finally gotten a site to site VPN working between my pfSense router and my parents’ Netgear Nighthawk R8000 running DD-WRT v3.

It was quite the undertaking for me to get these two systems talking. I drew a lot of inspiration from here. In order to get this to work you need to keep these things in consideration:

  • Protocol, port, device type, encryption cipher, hash algorithm, TLS authentication, and certificate settings all need to match
  • VPN IP addresses need to be assigned to both the server and the client
  • Routes for each network need to be established on both devices
  • Firewalls need to be configured to allow traffic to/from each network through the VPN tunnel

I used the following settings to get things working between these two devices:

OpenVPN Server (pfSense)

If you haven’t already, generate a certificate authority and server certificate. Do this in System / Cert Manager and click Add. When generating the certificate make sure the Certificate Type is Server Certificate.

General

  • Server mode: Peer to Peer (SSL / TLS)
  • Protocol: UDP
  • Device mode: tap

Cryptographic settings

  • Enable authentication of TLS packets: checked
  • Automatically generate a shared TLS authentication key: checked
  • Peer certificate authority & Server Certificate:  Select appropriate CA / certificate from the dropdowns here
  • DH Parameter length: 2048
  • Encryption algorithm: AES-256-CBC
  • Auth digest algorithm: SHA256 (256 BIT)
  • Certificate depth: One (Client + Server)

Tunnel Settings

  • IPv4 Tunnel network: Enter a unique (not existing on either netwonk) network here in CIDR format, ex 10.1.1.0/24
  • Ipv4 Local Network(s): Enter the networks you would like the remote network to access
  • IPv4 Remote Network(s): Enter the networks you would like the local network to access
  • Compression: Enabled with Adaptive Compression

Advanced Configuration

Optional? I found that for some reason the routing table wasn’t properly populated with the remote network on my pfSense server. I added a custom option to take care of that:

route <remote network> <remote subnet mask> <remote VPN IP>

In my example it ended up being “route 192.168.98.0 255.255.255.0 10.54.98.2”

Key export

You will need to export the Certificate Authority certificate as well as the client certificate & private key files for use with dd-wrt. Do this by going to System / Cert Manager. There are little icons to the right of the certificates where you can click to download them.

Export the CA certificate as well as both the certificate and key from whatever was specified in the Server Certificate section from the above OpenVPN configuration.

OpenVPN client (dd-wrt)

Go to Services / VPN and look for the OpenVPN Client section

  • Start OpenVPN Client: Enable
  • Tunnel Device: TAP
  • Tunnel Protocol: UDP
  • Encryption cipher: AES-256 CBC
  • Hash Algorithm: SHA256
  • User Pass Authentication: Disable
  • Advanced Options: Enable
  • LZO Compression: Adaptive
  • NAT: Enable
  • Firewall protection: Disable
  • Bridge TAP to br0: Enable
  • TLS Auth Key: <Paste the contents of the “Key” section under pfSense’s Cryptographic settings area of the OpenVPN server configuration>
  • CA Cert: <Paste contents of downloaded CRT file from pfsense’s CA>
  • Public Client Cert: <Paste contents of downloaded CRT file from pfsense’s certificate section>
  • Private Client Key: <Paste contents of downloaded .key file from pfsense’s certificate section>

IN THEORY this should be all that you have to do. The tunnel should establish and traffic should flow between both networks. Sadly it wasn’t that simple for my setup.

Troubleshooting

One-way VPN

After setting up the tunnel I saw everything was connected but the traffic was unidirectional (remote could ping local network but not visa versa.)

On the pfsense router, I ran

netstat -r | grep 192.168

(change the grep to whatever your remote network is)

I noticed that there were no routes to the remote network. To fix this I appended a server option in the OpenVPN server config (adjust this to match your networks)

route 192.168.98.0 255.255.255.0 10.54.98.2

Blocked by iptables

Adding the route on the server helped but things still weren’t getting through. I enabled logging on the DD-WRT side, consoled into the router, and ran the following:

watch -n 1 "dmesg | grep 192.168.98"

This revealed a lot of dropped packets from my OpenVPN server’s network. After a lot of digging I found this forum post that suggested a couple custom iptables rules to allow traffic between the bridged network and the OpenVPN network (adjust interface names as necessary)

iptables -I FORWARD -i br0 -o tap1 -j ACCEPT 
iptables -I FORWARD -i tap1 -o br0 -j ACCEPT

This doesn’t survive a reboot, so you’ll want to enter those two commands in the Administration / Commands section of the dd-wrt web configuration and click “Save Firewall”

Success

Finally, after a custom routing rule on the pfsense side and a custom iptables rule on the dd-wrt side, two way VPN has been established!

Connect Linux OpenVPN client to Netgear VPN Server

My parents got a shiny new Netgear R80000 wireless router which supports OpenVPN out of the box. The client configuration it generates doesn’t work right away, though, when I try to connect from my Linux Mint desktop. The connection is successful but I can’t ping or reach anything on the other network.

I discovered on this forum that you must add a couple options to the config file the router produces. You can do this either on the command line or by modifying the config file. The options are to add an interface to the VPN and to  create a route to the network, like so:

--ifconfig 192.168.1.5 255.255.255.0 --route 192.168.1.1

I took the generated non-windows VPN configuration from their router, unzipped it on my linux desktop, and then ran this command:

sudo openvpn --config parents.ovpn --ifconfig 192.168.1.5 255.255.255.0 --route 192.168.1.1

It worked like a charm.

Use OpenVPN from within crouton chroot

Update: Google released a ChromeOS update that broke the openvpn script. Find the updated version here.

Update 3/29/17: Added a DNS suffix line to fix broken DNS


I posted a little while ago about how to get openvpn working on your chromebook. That guide required that you run openvpn outside your chroot on the chromebook instance itself.

Lately I’ve been really feeling the need to have openvpn run within a crouton chroot instead. The solution is to take the script from the post above and divide it into two parts. One part you will still have to run outside your chroot but you will only have to do it once on each reboot. The other part can safely live inside your chroot.

First, on your chromebook itself (not in a chroot) make a small script to tell the shill service not to kill tun0:

sudo echo "
#!/bin/bash

#Allows the tun0 device to function
sudo stop shill
sudo start shill BLACKLISTED_DEVICES=tun0" > /usr/local/bin/shill

chmod +x /usr/local/bin/shill

Next, create this script within your chroot. Be sure to modify the environment variables to suit your setup.

#!/bin/bash

CONF_DIR="/path/to/directory/openvpn/config/is/in"
CONF_FILE="FILENAME_OF_OVPN_FILE"
NAMESERVER="IP_OF_DNS_SERVER_YOU_WANT_TO_USE"
SEARCH="DNS_SUFFIX_YOU_WANT_TO_USE"

cd "$CONF_DIR"

# Add google DNS on top of current ones, since openvpn command does not do it
sudo sed -i "1s/^/# new DNS\nsearch $SEARCH\nnameserver $NAMESERVER\n# old DNS\n/" /etc/resolv.conf

sudo openvpn --config "$CONF_FILE" --dev tun0

# When ctrl-c is hit remove tun0 and cleanup the DNS
sudo openvpn --rmtun --dev tun0
sudo sed -i '/# new DNS/,/# old DNS/d' /etc/resolv.conf
trap 2

Voila, we now have openvpn working inside our chroots again.

Fix openVPN on chromebooks

Edit: I’ve updated the script due to more updates in ChromeOS. Find the update here.


Around October of 2015 an update came out to Google Chromebooks that had an unfortunate side effect for me: openvpn no longer worked. Despite my having created a tunnel device seconds earlier, openvpn complained that a tunnel device didn’t exist.

I finally found a fix for this here. It turns out that the update caused the “shill” process to aggressively kill the tun0 interface. The clever workaround as posted by pippo0312 works flawlessly. It involves creating the openvpn tunnel in chromium itself rather than in a crouton chroot as I had previously done.

The original script took an argument for an ovpn file to use. Since I only have one VPN profile I just modified it to specify the ovpn file I use.

Place the script in /usr/local/bin on your chrome install (not a chroot) and mark it executable by issuing chmod +x

#!/bin/sh -e
trap '' 2
# Stop shill and restart it with a nicer attitude towards tun0
sudo stop shill
sudo start shill BLACKLISTED_DEVICES=tun0
# Sleep 10 seconds to allow chromebook to reconnect to the network
sudo sleep 10
sudo openvpn --mktun --dev tun0
sudo sleep 3
# Add google DNS on top of current ones, since openvpn command does not do it
sudo sed -i '1s/^/# new DNS\nnameserver 8.8.8.8\nnameserver 8.8.4.4\n# old DNS\n/' /var/run/shill/resolv.conf
# Lauch openvpn, finally...
sudo openvpn --config $1 --dev tun0
# When ctrl-c is hit remove tun0 and cleanup the DNS
sudo openvpn --rmtun --dev tun0
sudo sed -i '/# new DNS/,/# old DNS/d' /var/run/shill/resolv.conf
trap 2

Now you can just issue the command of the name of your script and vpn works again! hooray.

Fix POP/SMTP not working in Sophos UTM

It all started with an innocent enough e-mail:

Data Disk is filling up - please check. Current usage: 100%

I couldn’t find any clear information about what to do about this on Sophos’ forums. My data disk was full. What to do?

I can tell you what not to do – delete random files. I thought my solution would be to log into the UTM’s console and run a du -hsx /* to see where the space was. I found a large folder inside /var/storage – /var/storage/cores/httpd.16438. I removed it, because why not?

It turns out that did some weird things to my UTM. After removing that folder I kept getting spammed with these e-mails, once every hour:

Pop3 proxy not running - restarted

It took me a while to realize, but this also meant all e-mails relayed to the UTM were not being delivered. The entire POP/SMTP subsystem of the Sophos UTM was hosed. I could not find anything on the Sophos forums. After scratching my head I decided to have a deeper look at the logs. From the command line I issued

ls -ltr /var/log

and began reading the most recent logs.

pop3.log let me know what the problem was:

pop3proxy[9270]: Can't connect to database, retrying in 10 seconds: could not connect to server: Connection refused

I could not find any useful fixes for this error. I kept digging.

selfmon.log wasn’t much help other than to confirm that pop3 was having some serious issues. It was an endless abyss of repeated error messages:

selfmonng[3818]: W NOTIFYEVENT Name=pop3proxy_running Level=INFO Id=117 suppressed
...
selfmonng[3818]: W actionCmd(+): '/var/mdw/scripts/pop3 restart'

system.log put me on the right track:

ulogd[5107]: pg1: connect: could not connect to server: No such file or directory

 

Finally, we’re getting somewhere! After some searching I learned that pg1 is the postgresql database Sophos uses. I found a way to rebuild from this forum post.

One simple command did the trick:

/etc/init.d/postgresql92 rebuild

This rebuilt the postgresql database that I apparently corrupted when I removed files with reckless abandon. My e-mails work again!

Disable IPv6 on an interface in Linux

After tethering my phone to my laptop and googling “what is my ip” I was surprised to find an IPv6 address. Apparently my mobile carrier has implemented IPv6. Bravo to them.

Unfortunately, when I initiated my VPN, which is supposed to tunnel all traffic through it, my IP address didn’t change. This is because my VPN is IPv4 only. My system prioritizes IPv6 traffic, so if I happen to go to any IPv6 enabled site such as google, my VPN tunnel is bypassed entirely.

I don’t like the security implications of this. The long term solution is to implement IPv6 with my VPN; however while traveling I won’t be able to do that. The short term solution is to simply disable IPv6 for the interface that has it, in my case usb0 as that is what is tethered to my phone.

This simple command will do the trick:

sudo sh -c 'echo 1 > /proc/sys/net/ipv6/conf/usb0/disable_ipv6'

Change USB0 to whatever interface you would like (or all of them) and you’re done! Thanks to this site for the information.

 

 

 

Install OpenWRT on ASUS RT-16N

My parents’ ASUS RT-16N has been running dd-wrt for years now. I recently enhanced it with optware but something went horribly wrong after a few days. A drive out to their house revealed that the whole unit had spontaneously reset itself to factory defaults.

OpenWRT has come a long way since I last investigated it. I decided to give it another try as it’s till actively being developed whereas dd-wrt is not.

The wiki article on this device is a little bit out of date. I had to update it a little bit to get it to work.

To install OpenWRT on this device, SSH into it and run the following commands:

cd /tmp
wget http://downloads.openwrt.org/barrier_breaker/14.07/brcm47xx/generic/openwrt-brcm47xx-generic-squashfs.trx mtd -r write openwrt-brcm47xx-generic-squashfs.trx linux

That part went smoothly. The last part to configure was wireless N. After some searching I came across this post on the OpenWRT forums which worked nicely for me.  SSH into the router and do the following to enable full wireless N functionality:

opkg update
opkg install kmod-brcmsmac
opkg install kmod-brcmutil
rmmod b43
rmmod b43legacy
rmmod wl
rmmod brcmsmac
rmmod brcmutil
modprobe brcmsmac

# make sure to delete the old config files ... you have to ...
rm -f /etc/config/wireless 
wifi detect > /etc/config/wireless
vi /etc/config/wireless

Now comment out # "option disabled 1"

I had to take navid’s steps a little bit further by tweaking /etc/config/wireless a bit to add some features. My working wireless configuration is below:

config wifi-device 'radio0'
 option type 'mac80211'
 option channel '11'
 option hwmode '11ng'
 option path 'bcma0:0'
 list ht_capab 'GF'
 list ht_capab 'SHORT-GI-20'
 list ht_capab 'SHORT-GI-40'
 option txpower '19'
 option country '00'

config wifi-iface
 option device 'radio0'
 option network 'lan'
 option mode 'ap'
 option ssid 'SSID'
 option encryption 'psk2'
 option key 'SSIDKEY'

Success! Fully functional OpenWRT on my parents’ Asus RT-16N.