OpenVPN Routed Client Config for OpenWRT

In this case i want to access a remote network where also an OpenWRT Router is in use as the OpenVPN Client. This is a post in a series of OpenVPN Tutorials on this blog.

Network Topology

                    +------+
                    |      |
                    | IPv4 |
                +---+      +---+
                |   +------+   |
                |              |
+---------------+-+          +-+---------------+
| Router A        |          | Router B        |
|                 |          |                 |
| 192.168.68.0/24 |          | 192.168.34.0/24 |
| 192.168.68.1    |          | 192.168.34.1    |
+-+---------------+          +-^---------------+
  |                            |
  |                            |
+-v-------------+            +-+-------------+
| OpenVPN Tun   |            | OpenVPN Tun   |
| 172.16.0.0/29 |            | 172.16.0.0/29 |
| Server        |            | Client        |
| 172.16.0.1    |            | 172.16.0.2    |
+---------------+            +---------------+

I want to be able to reach net 192.168.34.0/24 from 192.168.68.0/24 and the other direction.

Creation of Client Certificates

See BlogPost Creation of RootCA Certificates. This Blogpost is on the ToDo list.

OpenWRT Config Settings – Routed Client

From /etc/config/openvpn

config openvpn 'cyber'
        option enabled '1'
#Protocol
        option client '1'
        option remote 'vpn.domain.tld 1194'        
        option dev_type 'tun'
        option dev 'cyber_tun0'
        option proto 'udp'        
        option topology 'subnet'
        option resolv_retry 'infinite'        
        option nobind '1'        
        option 'float' '1'
#Routes 
        option pull '1'
#Encryption
        option ca '/etc/ssl/certs/vpn.cavebeat.lan.ca-chain.cert.pem'
        option cert '/etc/ssl/certs/client1.vpn.cavebeat.lan.cert.pem'
        option key '/etc/ssl/private/client1.vpn.cavebeat.lan.key.pem'
        option tls_crypt '/etc/ssl/private/tls-auth.key'
        option cipher 'AES-256-CBC'
        option ncp-ciphers 'AES-256-GCM:AES-128-GCM:AES-256-CBC:AES-128-CBC'
        option auth 'SHA512'
        option tls_client '1'
        option tls_version_min '1.2'
        option tls_cipher 'TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384'
        option remote_cert_tls 'server'
        option verify_x509_name ‘vpn.domain.tld name’
#Logging
        option log '/var/log/openvpn.log'
        option status '/var/log/openvpn-status.log'
        option mute '5'
        option verb '4'
#Connection
        option compress 'lzo'
#Connection Reliability
        option persist_key '1'
        option persist_tun '1'
#Permissions
       option user 'nobody'
       option group 'nogroup'

Client Config

Most of the settings are already explained in the previous post OpenVPN Server Hardening – OpenWRT TUN Device. I’ll cover only the Client specific Settings which are new. For example the client config does not contain a DiffieHellman-Parameter setting.

--client 
  A helper directive designed to simplify the configuration of OpenVPN's client mode.  
--remote host [port] [proto] 
 Remote host name or IP address.  
 On the client, multiple --remote options may be specified for redundancy, each referring to a different OpenVPN server.  
 Specifying multiple --remote options for this purpose is a special case of the more general connection-profile feature.  
 See the <connection> documentation below. 
--resolv-retry n 
  If hostname resolve fails for --remote, retry resolve for n seconds before failing. 
  Set n to "infinite" to retry indefinitely.
--nobind 
  Do not bind to local address and port.  
  The IP stack will allocate a dynamic port for returning packets.  
  Since the value of the dynamic port could not be known in advance by a peer, this option is only suitable for peers which will be initiating connections by using the --remote option. 
--float 
 Allow remote peer to change its IP address and/or port number, such as due to DHCP (this is the default if --remote is not used). 
 --float when specified with --remote
 allows an OpenVPN session to initially connect to a peer at a known 
address, however if packets arrive from a new address and pass all 
authentication tests, the new address will take control of the session. 
 This is useful when you are connecting to a peer which holds a dynamic address such as a dial-in user or DHCP client. 
 Essentially, --float tells OpenVPN to accept authenticated packets from any address, not only the address which was specified in the --remote option. 
--pull 
  This option must be used on a client which is connecting to a multi-client server.  
  It indicates to OpenVPN that it should accept options pushed by the server, provided they are part of the legal set of pushable options (note that the --pull option is implied by --client ). 
  In particular, --pull allows the server to push routes to the client, so you should not use --pull or --client in situations where you don't trust the server to have control over the client's routing table. 
--tls-client 
  Enable TLS and assume client role during TLS handshake. 
--remote-cert-tls client|server 
  Require that peer certificate was signed with an explicit key usage and extended key usage based on RFC3280 TLS rules. 
  This is a useful security option for clients, to ensure that the host they connect to is a designated server.  
  Or the other way around; for a server to verify that only hosts with a client certificate can connect. 
--verify-x509-name name type 
  Accept connections only if a host's X.509 name is equal to name. 
  The remote host must also pass all other tests of verification. 
  Which X.509 name is compared to name depends on the setting of type. 
  type can be "subject" to match the complete subject DN (default), "name" to match a subject RDN or "name-prefix" to match a subject RDN prefix. 
  NOTE: Test against a name prefix only when you are using OpenVPN with a custom CA certificate that is under your control. 
  Never use this option with type "name-prefix" when your client certificates are signed by a third party, such as a commercial web CA. Client Config Dir on Server

CCD – Client Config Dir Settings

Client Config on Server

--client-config-dir dir 
  Specify a directory dir for custom client config files. 
  After a connecting client has been authenticated, OpenVPN will look in this directory for a file having the same name as the client's X509 common name. 
  If a matching file exists, it will be opened and parsed for client-specific configuration options. 
  If no matching file is found, OpenVPN will instead try to open and parse a default file called "DEFAULT", which may be provided but is not required. 
  Note that the configuration files must be readable by the OpenVPN process after it has dropped it's root privileges. 
  This file can specify a fixed IP address for a given client using --ifconfig-push, as well as fixed subnets owned by the client using --iroute.
  One of the useful properties of this option is that it allows client configuration files to be conveniently created, edited, or removed while the server is live, without needing to restart the server. 
  The following options are legal in a client-specific context: --push, --push-reset, --push-remove, --iroute, --ifconfig-push, and --config.
--ccd-exclusive 
  Require, as a condition of authentication, that a connecting client has a --client-config-dir file. 
On your server check the option client_config_dir ‘/etc/openvpn/ccd/’. In the defined ccd directory place a file for each client. The file must be named according to the X509 common name of the client certificate.
root@openwrt_server:~# cd /etc/openvpn/ccd/
root@openwrt_server:/etc/openvpn/ccd# ls
client1.vpn.cavebeat.lan
root@openwrt_server:/etc/openvpn/ccd# cat client1.vpn.cavebeat.lan 
ifconfig-push 172.16.10.2 255.255.255.248 
iroute 192.168.34.0 255.255.255.0

Client Config File

ifconfig-push tells the client the IP address and the netmask. iroute routes the packet from openvpn to the client in combination with route on the server.

--ifconfig-push local remote-netmask [alias]
  Push virtual IP endpoints for client tunnel, overriding the --ifconfig-pool dynamic allocation.
  The parameters local and remote-netmask are set according to the --ifconfig directive which you want to execute on the client machine to configure the remote end of the tunnel. 
  Note that the parameters local and remote-netmask are from the perspective of the client, not the server. 
  They may be DNS names rather than IP addresses, in which case they will be resolved on the server at the time of client connection.
--iroute network [netmask] 
  Generate an internal route to a specific client. 
  The netmask parameter, if omitted, defaults to 255.255.255.255. 
  This directive can be used to route a fixed subnet from the server to a particular client, regardless of where the client is connecting from.
  Remember that you must also add the route to the system routing table as well (such as by using the --route directive).
  The reason why two routes are needed is that the --route directive routes the packet from the kernel to OpenVPN. 
  Once in OpenVPN, the --iroute directive routes to the specific client. 
  This option must be specified either in a client instance config file using --client-config-dir or dynamically generated using a --client-connect script. 
  The --iroute directive also has an important interaction with --push "route ...". 
  --iroute essentially defines a subnet which is owned by a particular client (we will call this client A). 
  If you would like other clients to be able to reach A's subnet, you can use --push "route ..." together with --client-to-client to effect this.
  In order for all clients to see A's subnet, OpenVPN must push this route to all clients EXCEPT for A, since the subnet is already owned by A.
  OpenVPN accomplishes this by not not pushing a route to a client if it matches one of the client's iroutes. 

Route Settings on Server

On the server two route settings must be set. The first one is to tell the Server Router where to send packets for the client network. The push route is to tell the clients where to send packets to the server network.

option route '192.168.34.0 255.255.255.0 172.16.10.1'
list push 'route 192.168.68.0 255.255.255.0'

Firewall

For more details on this part, have also a look at my other VPN Client Tutorial.

Create Unmanaged Interface

Your /etc/config/network should contain now

root@openwrt:~# cat /etc/config/network 
config interface 'cyber_vpn'
 option proto 'none'
 option ifname 'cyber_tun0'
 option auto '1'

Firewal Zones

Your /etc/config/firewall should contain now following parts:

cat /etc/config/firewall 
config zone
 option name 'cyber_vpn'
 option input 'ACCEPT'
 option output 'ACCEPT'
 option network 'cyber_vpn'
 option forward 'ACCEPT'

config forwarding
 option dest 'lan'
 option src 'cyber_vpn'

config forwarding
 option dest 'cyber_vpn'
 option src 'lan'

Routing Table and Ping Checks

These routes should show up on Client and Server to be reach able from both ways.

Client

root@openwrt_client:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.16.10.0 0.0.0.0 255.255.255.248 U 0 0 0 cyber_tun0
192.168.68.0 172.16.10.1 255.255.255.0 UG 0 0 0 cyber_tun0
192.168.34.0 0.0.0.0 255.255.255.0 U 0 0 0 br-lan

Ping the Server Router from the Client Router

root@openwrt_client:~# ping -c 2 192.168.68.1
PING 192.168.96.1 (192.168.34.1): 56 data bytes
64 bytes from 192.168.34.1: seq=0 ttl=64 time=45.757 ms
64 bytes from 192.168.34.1: seq=1 ttl=64 time=37.271 ms
--- 192.168.34.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 37.271/41.514/45.757 ms

Ping the remote and local OpenVPN IP

root@openwrt_client:~# ping -c 2 172.16.10.1
PING 172.16.10.1 (172.16.10.1): 56 data bytes
64 bytes from 172.16.10.1: seq=0 ttl=64 time=49.015 ms
64 bytes from 172.16.10.1: seq=1 ttl=64 time=55.041 ms
--- 172.16.10.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 49.015/52.028/55.041 ms

root@openwrt_client:~# ping -c 2 172.16.10.2
PING 172.16.10.2 (172.16.10.2): 56 data bytes
64 bytes from 172.16.10.2: seq=0 ttl=64 time=0.289 ms
64 bytes from 172.16.10.2: seq=1 ttl=64 time=0.277 ms
--- 172.16.10.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.277/0.283/0.289 ms

Server

root@openwrt_server:~# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.16.10.0 0.0.0.0 255.255.255.248 U 0 0 0 cyber_tun0
192.168.34.0 172.16.10.1 255.255.255.0 UG 0 0 0 cyber_tun0
192.168.68.0 0.0.0.0 255.255.255.0 U 0 0 0 br-lan

Ping the Client Router from the Server Router

root@openwrt:~# ping -c 2 192.168.34.1 
PING 192.168.96.1 (192.168.68.1): 56 data bytes
64 bytes from 192.168.68.1: seq=0 ttl=64 time=43.559 ms
64 bytes from 192.168.68.1: seq=1 ttl=64 time=34.661 ms
--- 192.168.68.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 34.661/39.110/43.559 ms

Ping the local and remote OpenVPN IP

root@openwrt:~# ping -c 2 172.16.10.1
PING 172.16.10.1 (172.16.10.1): 56 data bytes
64 bytes from 172.16.10.1: seq=0 ttl=64 time=0.437 ms
64 bytes from 172.16.10.1: seq=1 ttl=64 time=0.282 ms
--- 172.16.10.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.282/0.359/0.437 ms

root@openwrt_server:~# ping -c 2 172.16.10.2
PING 172.16.10.2 (172.16.10.2): 56 data bytes
64 bytes from 172.16.10.2: seq=0 ttl=64 time=42.780 ms
64 bytes from 172.16.10.2: seq=1 ttl=64 time=33.573 ms
--- 172.16.10.2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 33.573/38.176/42.780 ms

 

Comments are closed.