OpenVPN - Multihomed Fedora Server

SUMMARY

I have been playing around with OpenVPN for awhile now, but never committed to it. However, after seeing some various posts, and the enhancement with Android phones/apps, and the ease and advantages of a personal VPN, I decided to give it a go. My biggest roadblock was that my primary server, was a DNS, DHCP, HTTP, SSH, iptables, multihomed server, and I wanted to make sure that the VPN clients (work PC, Android Tablet, Android Phone) would be able to connect, act like "the server", and be able to access all the internal services and devices. In the end, here are the steps/config files that worked for me, and resulted in the above desired configuration.

Taken from https://community.openvpn.net/openvpn/wiki/BridgingAndRouting
this was the overall picture of what I was trying to achieve:

INSTRUCTIONS

In addition to the above BridgingAndRouting documentation, I also followed https://fedoraproject.org/wiki/Openvpn

  • yum install openvpn.$HOSTTYPE easy-rsa
  • cp -ai /usr/share/openvpn/easy-rsa/2.0 ~/easy-rsa
  • cd ~/easy-rsa
  • vi vars
  • . vars
  • ./clean-all
  • ./build-ca
  • ./build-inter $( hostname | cut -d. -f1 )
  • ./build-dh
  • mkdir /etc/openvpn/keys
  • cp -ai keys/$( hostname | cut -d. -f1 ).{crt,key} keys/ca.crt keys/dh*.pem /etc/openvpn/keys/
  • cp -ai /usr/share/doc/openvpn-*/sample/sample-config-files/roadwarrior-server.conf /etc/openvpn/server.conf
  • ln -s /lib/systemd/system/openvpn\@.service /etc/systemd/system/multi-user.target.wants/openvpn\@server.service
  • systemctl -f enable openvpn@server.service

With that out of the way, and after some troubleshooting and experitmenting, here are the config files I used:

########################################
# /etc/openvpn/server.conf
#

port 1194
dev tun

# TLS parms
tls-server
ca keys/ca.crt
cert keys/lup64.crt
key keys/lup64.key
dh keys/dh1024.pem

# Tell OpenVPN to be a multi-client udp server
mode server

# The server's virtual endpoints
ifconfig 10.8.0.1 10.8.0.2

# Pool of /30 subnets to be allocated to clients.
# When a client connects, an --ifconfig command
# will be automatically generated and pushed back to
# the client.
ifconfig-pool 10.8.0.4 10.8.0.255

# Push the correct gateway to client - allows client to act like server (whatsmyip)
push "redirect-gateway def1 bypass-dhcp"

# Push route to client to bind it to our local
# virtual endpoint.
push "route 10.8.0.1 255.255.255.255"

# Push DHCP/DNC options - allows client to use internal LAN DNS services
push "dhcp-option DOMAIN thelupine.com"
push "dhcp-option SEARCH thelupine.com"
push "dhcp-option DNS 10.8.0.1"

# Client should attempt reconnection on link
# failure.
keepalive 10 60

# Delete client instances after some period
# of inactivity.
inactive 600

# Route the --ifconfig pool range into the
# OpenVPN server.
route 10.8.0.0 255.255.255.0

# The server doesn't need privileges
user openvpn
group openvpn

# Keep TUN devices and keys open across restarts.
persist-tun
persist-key

log-append /var/log/openvpn.log

verb 1

I made sure that my named service (DNS) was listening on the new 10.8.0.1 network/interface. That was done with a simple edit to /etc/named.conf and the following updated lines:

listen-on port 53 { 127.0.0.1; 192.168.10.1; 10.8.0.1;};
allow-query     { localhost; 192.168.10.0/24; 10.8.0.0/24;};

Last was my updated iptables config file. This is the same script I've used for years, so I just needed to allow some traffic from the new tun0 interface. Here are the additions to the script, using some obvious variables:

IPTABLES=`which iptables`
IFCONFIG=`which ifconfig`
EXTIF="p9p1"
EXTIP="`$IFCONFIG $EXTIF | grep 'inet ' | sed 's/.*inet //' | sed 's/ netmask.*//'`"
INTIF="p12p1"
INTIP="192.168.10.1"
INTNET="192.168.10.0/24"
VPNIF="tun0"
VPNNET="10.8.0.0/24"
UNIVERSE="0.0.0.0/0"

$IPTABLES -A INPUT -s $VPNNET -j ACCEPT
$IPTABLES -A INPUT -i $EXTIF -p udp -d $EXTIP --dport 1194 -j ACCEPT # VPN port
# FORWARD local networks to local networks (aka vpn to lan)
$IPTABLES -I FORWARD -o $INTIF -i $VPNIF -d $INTNET -s $VPNNET -j ACCEPT
$IPTABLES -I FORWARD -i $INTIF -o $VPNIF -s $INTNET -d $VPNNET -j ACCEPT

There is obviously more to the script. These are just the parts specific to VPN.

OK, with all the above in place, I restarted all the necessary services:

  • systemctl restart openvpn@server.service
  • systemctl restart named.service
  • /etc/firewall/firewall.stop && /etc/firewall/firewall.start

----------------------------------------------------------------------------------------------------------------------

That was it for the server part. Next, I created the necessary certs and files for the client.

  • cd ~/easy-rsa
  • . vars
  • ./build-key username

Finally, I used the above generated cert files, and created a thelupine.ovpn file, that Android devices could import:

client
proto udp
remote servername.thelupine.com
port 1194
dev tun
nobind

key-direction 1


-----BEGIN CERTIFICATE-----
#found in file ca.crt
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
#found in file username.crt
-----END CERTIFICATE-----

-----BEGIN PRIVATE KEY-----
#found in file username.key
-----END PRIVATE KEY-----

I copied the thelupine.ovpn file to various places so that I could get to it, and import it on my Android phone and Android tablet. With that imported, the devices instantly connected, and I was able to access all my internal devices (SSH, VNC, etc.). I'll be removing some of those ports from the firewall now, as I'll only need to get to them via the VPN from now on. Also, when I type "what is my IP" in a Google search, it isn't showing me the Sprint IP on the phone, it's showing me the server IP that I'm connected to.

Very happy with the results, but if you see something wrong, or know of a better way to do things, please feel free to comment and let me know.

Pages