OpenVPN server on Fedora 16 connecting Cyanogenmod (7.1) Android phone [bridged]

Intro

I have already posted about openVPN on Ubuntu  but the config for Fedora is a little different so here’s a updated post. I did the following setup using

I’ve used this quite a lot and its been very stable 😀 Have to say OpenVPN is pretty awesome. Seems very stable even when transitioning between 2G & 3G.

~~~~~~~~~~

There is a more up to date version of this topic [here]. It shows how to configure a routed connection but that is the recommended connection type unless you need bridged.

Server Setup

First of all we need to make sure we have bridge-utils and the OpenVPN package installed.

yum install -y openvpn bridge-utils

Network interfaces

For this to work we need to create a logical bridge interface and then add physical interfaces to the bridge. So first we create a file /etc/sysconfig/network-scripts/ifcfg-br0 and add the following:

DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=10.10.10.21
NETMASK=255.255.255.0
GATEWAY=10.10.10.21
DELAY=0
STP=off

Save the file and open the file /etc/sysconfig/network-scripts/ifcfg-Wired_connection_1 (file names may vary depending on the setup of your machine). Basically we want to remove IP addressing and add it to the bridge group. Change this file accordingly (there’s no need to change the HWADDR info that’s already there)


HWADDR=BE:EF:BE:EF:BE:EF
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
BRIDGE=br0

Now we should be able to restart the network service and have full connectivity to/from the server.

service network restart

If you still can browse to/from the server as usual dont carry on any further something is b0rked. Check /etc/resolve.conf has valid DNS servers etc.

Server Certificates

Now we need to generate certificates for our server to use. OpenVPN comes with some scripts to take most of the pain out of this. To keep things where I can find them I like to move these to /etc/openvpn/easy-rsa. First off we make a new directory and copy the scripts into it.

mkdir /etc/openvpn/easy-rsa
cd /etc/openvpn
cp -R /usr/share/openvpn/easy-rsa/2.0/* easy-rsa/
cd easy-rsa

Edit the following in the vars file of this directory

export KEY_COUNTRY="UK"
export KEY_PROVINCE="M0"
export KEY_CITY="m00nieTown"
export KEY_ORG="m00nie.co"
export KEY_EMAIL="spam@weeeeeimaspamer.com"

Now just run the following commands

source ./vars ## execute your new vars file
./clean-all  ## Setup the easy-rsa directory (Deletes all keys)
./build-dh  ## takes a while consider backgrounding
./pkitool --initca ## creates ca cert and key
./pkitool --server server ## creates a server cert and key
cd keys
openvpn --genkey --secret ta.key  ## Build a TLS key
sudo cp server.crt server.key ca.crt dh1024.pem ta.key ../../
cd ../..

Server Config

Create a directory and two files. One called ifup.sh and one called ifdown.sh. These will be used to control bringing the interfaces up/down and should contain the following.

mkdir /etc/openvpn/ifupdown
touch /etc/openvpn/ifupdown/ifup.sh
touch /etc/openvpn/ifupdown/ifdown.sh
sudo chmod +x /etc/openvpn/ifupdown/ifup.sh /etc/openvpn/ifupdown/ifdown.sh

ifup.sh

#!/bin/sh

BR=$1
DEV=$2
MTU=$3
/sbin/ip link set "$DEV" up promisc on mtu "$MTU"
/usr/sbin/brctl addif $BR $DEV

ifdown.sh

#!/bin/sh

BR=$1
DEV=$2

/usr/sbin/brctl delif $BR $DEV
/sbin/ip link set "$DEV" down

Now to edit the /etc/openvpn/server.conf file. Mine looks like the following

mode server
tls-server
local 10.10.10.21 ## ip/hostname of server
port 12345 ## My Custom port
proto udp
#bridging directive
dev tap0 ## If you need multiple tap devices, add them here
up "/etc/openvpn/ifupdown/ifup.sh br0"
down “/etc/openvpn/ifupdown/ifdown.sh br0″
persist-key
persist-tun
#certificates and encryption
ca ca.crt
cert server.crt
key server.key # This file should be kept secret
dh dh1024.pem
tls-auth ta.key 0 # This file is secret
cipher BF-CBC # Blowfish (default)
comp-lzo
#DHCP Information
ifconfig-pool-persist ipp.txt
server-bridge 10.10.10.21 255.255.255.0 10.10.10.240 10.10.10.250
push “dhcp-option DNS 8.8.8.8″
push “dhcp-option DOMAIN m00nie.com”
max-clients 10 ## set this to the max number of clients that should be connected at a time
#log and security
user nobody
group nogroup
keepalive 10 120
status openvpn-status.log
script-security 2 ## This needed added
verb 4 ##Changed the logging level

You should be able to run the server with the following command and recieve no errors. If you do fix them first

openvpn --config server.conf --script-security 2

If it all looks good lets make OpenVPN run as a service and start when the server boots

systemctl start openvpn.service
systemctl enable openvpn.service

Client Setup

We need to create some certificates for our client (the phone)

cd /etc/openvpn/easy-rsa
source ./vars             ## execute the vars file
./pkitool phone          ## create a cert and key named "phone"

Now to make it easy to import to my phone I made a p12 file

cd keys
openssl pkcs12 -export -in phone.crt -inkey phone.key -certfile ca.crt -out phone.p12
mv phone.p12 /var/www/html

Now browse to the file on your phone E.g http://10.10.10.21/phone.p12. Your phone will then store the certificates into is credential store 🙂 Finally we configure the VPN under Settings > Wireless & networks > VPN settings > Add VPN like so

The main config:

Menu > Advanced OpenVPN Settings:

At the moment there is no gui setting to configure tls-auth but they did give us the Extra arguments option. In here I added (I used FTP to copy the ta.key file to the phone in a directory called VPN.

--tls-auth /mnt/sdcard/VPN/ta.key 1 --explicit-exit-notify 2

Router Setup

Time for some evil NAT. The basic syntax is

ip nat inside source static udp <fedora server IP> <server port> interface <outside address>  <some port>

so mine was

ip nat inside source static udp 10.10.10.21 12345 interface dialer 0 12345

Now we can see the static translation:

m00nies_router#show ip nat translations
Pro Inside global Inside local Outside local Outside global
udp 192.168.1.1:12345 10.10.10.21:12345 --- ---

Now the port is forwarding to the OpenVPN server but my zone based firewall config is dropping the packets.

Apr 13 18:14:04.136: %FW-6-DROP_PKT: Dropping udp session 172.16.1.1 10.1.1.10:12345 on zone-pair out-in class class-default due to DROP action found in policy-map with ip ident 0

At the moment there is no explicit zone-pair for outside to inside so the default is deny all. Lets define one

m00nies_router#conf t
Enter configuration commands, one per line. End with CNTL/Z.
m00nies_router(config)#access-list 199 permit udp any any eq 12345
m00nies_router(config)#class-map type inspect match-all OPENVPN
m00nies_router(config-cmap)# match access-group 199
m00nies_router(config-cmap)# exit
m00nies_router(config)#policy-map type inspect OPENVPN_POLICY
m00nies_router(config-pmap)#class type inspect OPENVPN
m00nies_router(config-pmap-c)#pass log
m00nies_router(config-pmap-c)#exit
m00nies_router(config-pmap)#exit
m00nies_router(config)#zone-pair security out-in source out-zone destination in-zone
m00nies_router(config-sec-zone-pair)# service-policy type inspect OPENVPN_POLICY
m00nies_router(config-sec-zone-pair)#^Z
m00nies_router#

First off we classify the traffic we want the allow it to pass but log it. Next we apply that policy to a zone pair. Theres more info about configuring ZBFW [here]. Below we can see the default that catches all other traffic is still drop.

m00nies_router#show policy-map type inspect OPENVPN_POLICY
Policy Map type inspect OPENVPN_POLICY
Class OPENVPN
Pass log
Class class-default
Drop

Now we can try our VPN access.
It passes the router ok

Apr 13 18:31:00.085: %FW-6-PASS_PKT: (target:class)-(out-in:OPENVPN) Passing udp pkt 172.16.1.1:52585 => 10.10.10.21:12345 with ip ident 0

And the OpenVPN server logs confirm it works ok too. Its been very stable on both 2 and 3G.

moonie 🙂

Comments

  • Can you clarify: your openvpn server and router are the same machine in this example, right? How would you set up the bridge stuff if you’re using a separate box for openvpn?

    I’ve got a crappy router that won’t do static IP assignments and a plug computer with F14. I want to use DHCP on eth0 of the plug, and pick a static high number on an eth0:0 alias, and do whatever bridging there (not sure). The router can forward from the outside to eth0:0 on the plug.

    Also, the section where you talk about tls auth on the client side — could you maybe explain what’s up with that a bit more? Where are you getting ta.key, why does it matter?

  • My OpenVPN server is not the same machine as my router. They are seperate boxes so the config for you should be very similar to the above.

    ta.key is for the TLS auth feature of OpenVPN. You can check out more of what it means [here]

  • This is a great guide but modifying the existing wired connection:
    /etc/sysconfig/network-scripts/ifcfg-Wired_connection_1

    Doesn’t make any sense for me. First because this file doesn’t exist for me, I only have the em1 adapter. Second if I remove the BootProto=dhcp then my local adapter ceases to operate on my LAN, which is a bad thing.

    What am I missing here should I create this file?

  • Hi LC

    This file should already exist (although may be named differently depending on your setup). Do a ifconfig and check what your current interface is called. Removing dhcp from the interface shouldn’t stop it working if you configure suitable ip/mask/gateway. Id check your current ifconfig first though. 🙂

    m00nie

  • That script just doesn’t exist for me. Maybe you have a nonstandard setup,
    I installed F16 from scratch, and perhaps if you upgraded your box you had
    a previous networkmanager config that persisted through the upgrade from
    some older version of Fedora.

    I ended up configuring a routed connection instead because I really don’t need bridging,
    just SMB access to certain servers on the network.

    My client is an android epic 4g with the CleanGB Rom installed and using OpenVpn apk.

    Steps:
    1. download the tun.ko module appropriate for your kernel. you can check if tun.ko loads correctly by running a terminal emulator, switching to root (using su) and then typing insmod tun.ko and see if it returns without any errors.

    2. Most people don’t need bridged. For my configuration I simply went with a routed setup.

    3. F16 no longer uses chkconfig, and systemd does not automatically provide you with a way of configuring the openvpn systemd service. I had to create this manually.

    here is the process:
    ln -s /lib/systemd/system/openvpn@.service /etc/systemd/system/multi-user.target.wants/openvpn@.service

    #systemctl daemon-reload
    #systemctl enable openvpn@.service
    #systemctl restart openvpn@.service

    4. Make sure IP Forwarding is setup:
    #cat /proc/sys/net/ipv4/ip_forward
    1

    If it returns 0 then

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

    5. Iptables Configuration for /etc/sysconfig/iptables:

    -A INPUT -m state –state NEW -m udp -p udp –dport 1194 -j ACCEPT (you don’t need both, either udp or tcp, I am using tcp)
    -A INPUT -m state –state NEW -m tcp -p tcp –dport 1194 -j ACCEPT
    -A INPUT -i tap+ -j ACCEPT
    -A FORWARD -i tap+ -j ACCEPT
    -A FORWARD -i em1 -o tap+ -j ACCEPT
    -A FORWARD -i em1 -o tap+ -m state –state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -j REJECT –reject-with icmp-host-prohibited
    -A FORWARD -j REJECT –reject-with icmp-host-prohibited

    My local lan subnet is 192.168.1.0/24

    6. Here is my server config:
    # cat talon.conf
    mode server
    tls-server
    server 10.8.0.0 255.255.255.0 ## ip/hostname of server
    port 1194 ## My Custom port
    proto tcp-server
    dev tap ## If you need multiple tap devices, add them here
    push “route 192.168.1.0 255.255.255.0”
    persist-key
    persist-tun

    #certificates and encryption
    ca ca.crt
    cert talon.crt
    key talon.key # This file should be kept secret
    dh dh1024.pem
    ##tls-auth tlsauth.key 0 # This file is secret (haven’t enabled tls auth yet on client)
    #cipher BF-CBC # Blowfish (default) #might not work on all android openvpn clients
    comp-lzo

    #DHCP Information
    push dhcp-option DOMAIN yourdomainname
    max-clients 10 ## set this to the max number of clients that should be connected at a time
    #log and security
    user nobody
    group nobody (note that group nogroup does not exist for me)
    keepalive 10 120
    status /var/log/openvpn-status.log
    log-append /var/log/openvpn.log
    script-security 2

    7. Client side config:

    One note here: ./pkitool phone was not working for me, it would create an empty certificate file.
    After much fuss I just ran clean-all and used ./build-req phone and I think I also ran ./sign-req phone.

    client.ovpn:
    client
    dev tap
    dev-node /dev/tun
    proto tcp
    remote
    resolv retry infinite
    persist-key
    persist-tun
    ca ca.crt
    cert
    key
    ns cert-type-server
    comp-lzo
    verb 3
    log-append openvpn.log
    status openvpn-status.log

    If you need to have your LAN Clients communicate back to your phone I
    suggest adding a static route to your default LAN gateway (which is normally a router that openvpn is not running on) (I am forwarding port 1194 from my gateway to my internal linux openvpn server).

    static route to add on gateway:
    10.8.0.0 255.255.255.0 <ip address of openvpn server eth0 interface)

    Thanks,

    LC

Leave a Reply