User Tools

Site Tools


doc:howto:vpn.openvpn

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
doc:howto:vpn.openvpn [2014/03/01 20:19]
zxdavb
doc:howto:vpn.openvpn [2016/07/26 07:11] (current)
tongfa [Route All Client Traffic Through the Tunnel]
Line 1: Line 1:
 +====== OpenVPN Setup Guide for Beginners ====== ​
 +This is a beginner'​s guide to setting up OpenVPN on a server and a client where, in this instance, both are running OpenWrt (although the OpenVPN client could easily be running on another OS, such as Windows or Linux).
 +
 +For non-beginners or real-world tunnels, [[doc/​howto/​vpn.server.openvpn.tun]] may be a better place to start.
 +
 +The primary goal of this HOWTO is to get a working OpenVPN tunnel; the strategy used by this HOWTO is to keep it simple. ​ Because of that, this is a very basic OpenVPN tunnel configuration that will not suit most people'​s needs without further configuration. However, once the basic tunnel is working, additional recipes for other use-cases can be found at [[doc/​howto/​vpn.server.openvpn.tun]].
 +
 +For an overview of all VPN-related articles (including other VPN technologies),​ see [[doc/​howto/​vpn.overview]].
 +
 +===== Use Case (the beginner'​s configuration) =====
 +The user wants a client to access their OpenWrt router without the possibility of being snooped. That is, the user can already access the router, but over a public network, such as the Internet.  ​
 +
 +The end result will be a private connection directly between the OpenVPN client and server. Mostly, it is as if the two end-points are on the same subnet (but not on the same subnet as your router'​s LAN).
 +
 +To facilitate configuration/​testing,​ this HOWTO permits two distinct scenarios for this use-case:
 +  * Scenario 0: the OpenVPN client can ping the OpenWrt router via the router'​s LAN interface. Specifically,​ they are on the same subnet (e.g. the client is a DHCP client of the OpenWrt router).
 +  * Scenario 1: the OpenVPN client can ping the OpenWrt router via the router'​s WAN interface. Specifically,​ they are **not** on the same subnet (e.g. they are separated by the Internet).
 +
 +Scenario 0 takes out much of the complexity of real-world configurations,​ such as the vagaries of the Internet, or your OpenWrt firewall configuration. Scenario 0 allows you to easily implement an OpenVPN tunnel, which can then be switched to Scenario 1, which itself is the basis for most real-world OpenVPN configurations. You can either start with Scenario 0, and switch to Scenario 1 when you've got it working, or start directly with Scenario 1 and switch back to Scenario 0 for troubleshooting.
 +
 +===== Prerequisites =====
 +This HOWTO requires that the OpenVPN server is an OpenWrt router running OpenWrt 15.05 Chaos Calmer.
 +
 +===== Install the required software =====
 +<​code>​
 +opkg update
 +opkg install openvpn-openssl openvpn-easy-rsa
 +</​code>​
 +
 +===== Create the certificates =====
 +<​code>​
 +build-ca
 +build-dh
 +build-key-server my-server
 +build-key-pkcs12 my-client
 +</​code>​
 +
 +The above creates a server certificate named //​my-server//​ and a client certificate named //​my-client//​. You can create multiple client certificates by running ''​build-key-pkcs12''​ multiple times and specifying different names.
 +
 +You can create a new set of certificates by running ''​clean-all''​ and then the above commands again.ls
 +
 +
 +===== Distribute the certificates =====
 +<​code>​
 +cp /​etc/​easy-rsa/​keys/​ca.crt /​etc/​easy-rsa/​keys/​my-server.* /​etc/​easy-rsa/​keys/​dh2048.pem /​etc/​openvpn
 +scp /​etc/​easy-rsa/​keys/​ca.crt /​etc/​easy-rsa/​keys/​my-client.* root@CLIENT_IP_ADDRESS:/​etc/​openvpn
 +</​code>​
 +
 +The above assumes that you can connect to the client from the server, that the client has a SSH server and that you can login as root. If you can't, transfer the client certificate some other way, such as using an USB stick.
 +
 +===== Configure the network on the OpenWrt server =====
 +  - Create the VPN interface: (if not running server-bridge)<​code bash>
 +uci set network.vpn0=interface
 +uci set network.vpn0.ifname=tun0
 +uci set network.vpn0.proto=none
 +uci set network.vpn0.auto=1
 +</​code>​
 +  - Add interface to bridge: :!: skip unless going for server-bridge config<​code bash>
 +uci set network.lan.ifname="​$(uci get network.lan.ifname) tap_myvpn"​
 +</​code>​
 +  - Allow inbound VPN traffic:<​code bash>
 +uci add firewall rule
 +uci set firewall.@rule[-1].name=Allow-OpenVPN-Inbound
 +uci set firewall.@rule[-1].target=ACCEPT
 +uci set firewall.@rule[-1].src=*
 +uci set firewall.@rule[-1].proto=udp
 +uci set firewall.@rule[-1].dest_port=1194
 +</​code>​
 +  - Allow OpenVPN tunnel utilization:​ (not needed when bridging using tap)<​code bash>
 +uci add firewall zone
 +uci set firewall.@zone[-1].name=vpn
 +uci set firewall.@zone[-1].input=ACCEPT
 +uci set firewall.@zone[-1].forward=REJECT
 +uci set firewall.@zone[-1].output=ACCEPT
 +uci set firewall.@zone[-1].network=vpn0
 +uci add firewall forwarding
 +uci set firewall.@forwarding[-1].src='​vpn'​
 +uci set firewall.@forwarding[-1].dest='​wan'​
 +</​code>​
 +  - Commit the changes:<​code bash>
 +uci commit network
 +/​etc/​init.d/​network reload
 +uci commit firewall
 +/​etc/​init.d/​firewall reload
 +</​code>​
 +
 +===== Configure the network on the OpenWrt client =====
 +Do the same as on the OpenWrt server above except skip step 2.
 +
 +===== Configure the OpenVPN server =====
 +<​code=bash>​
 +echo > /​etc/​config/​openvpn # clear the openvpn uci config
 +uci set openvpn.myvpn=openvpn
 +uci set openvpn.myvpn.enabled=1
 +uci set openvpn.myvpn.verb=3
 +uci set openvpn.myvpn.port=1194
 +uci set openvpn.myvpn.proto=udp
 +uci set openvpn.myvpn.dev=tun
 +uci set openvpn.myvpn.server='​10.8.0.0 255.255.255.0'​
 +uci set openvpn.myvpn.ca=/​etc/​openvpn/​ca.crt
 +uci set openvpn.myvpn.cert=/​etc/​openvpn/​my-server.crt
 +uci set openvpn.myvpn.key=/​etc/​openvpn/​my-server.key
 +uci set openvpn.myvpn.dh=/​etc/​openvpn/​dh2048.pem
 +uci commit openvpn
 +/​etc/​init.d/​openvpn enable
 +/​etc/​init.d/​openvpn start
 +</​code>​
 +
 +===== Configure the OpenVPN server (ethernet bridge) =====
 +:!: new and untested, !!!! doesn'​t work, the interface is created, but not added to bridge
 +<​code=bash>​
 +echo > /​etc/​config/​openvpn # clear the openvpn uci config
 +uci set openvpn.myvpn=openvpn
 +uci set openvpn.myvpn.enabled=1
 +uci set openvpn.myvpn.verb=3
 +uci set openvpn.myvpn.port=1194
 +uci set openvpn.myvpn.proto=udp
 +uci set openvpn.myvpn.dev=tap_myvpn
 +uci set openvpn.myvpn.mode=server
 +uci set openvpn.myvpn.tls_server=1
 +uci set openvpn.myvpn.persist_tun=1
 +uci set openvpn.myvpn.push='​route-gateway dhcp'
 +uci set openvpn.myvpn.ca=/​etc/​openvpn/​ca.crt
 +uci set openvpn.myvpn.cert=/​etc/​openvpn/​my-server.crt
 +uci set openvpn.myvpn.key=/​etc/​openvpn/​my-server.key
 +uci set openvpn.myvpn.dh=/​etc/​openvpn/​dh2048.pem
 +uci commit openvpn
 +/​etc/​init.d/​openvpn enable
 +/​etc/​init.d/​openvpn start
 +</​code>​
 +===== Configure the OpenWrt client =====
 +<​code=bash>​
 +echo > /​etc/​config/​openvpn
 +uci set openvpn.myvpn=openvpn
 +uci set openvpn.myvpn.enabled=1
 +uci set openvpn.myvpn.dev=tun
 +uci set openvpn.myvpn.proto=udp
 +uci set openvpn.myvpn.verb=3
 +uci set openvpn.myvpn.ca=/​etc/​openvpn/​ca.crt
 +uci set openvpn.myvpn.cert=/​etc/​openvpn/​my-client.crt
 +uci set openvpn.myvpn.key=/​etc/​openvpn/​my-client.key
 +uci set openvpn.myvpn.client=1
 +uci set openvpn.myvpn.remote_cert_tls=server
 +uci set openvpn.myvpn.remote="​SERVER_IP_ADDRESS 1194"
 +uci commit openvpn
 +/​etc/​init.d/​openvpn start
 +</​code>​
 +
 +Or alternatively drop an openvpn configuration file into /​etc/​openvpn/<​vpnName>​.conf. ​ You can test it in a shell with <​code>​openvpn /​etc/​openvpn/​myVpnName.conf</​code>​
 +===== Configure other clients =====
 +Create the following OpenVPN client configuration file, save it with an ''​.ovpn''​ extension in the Windows or ''​.conf''​ in the *nix and give it to your client:
 +
 +<​code>​
 +dev tun
 +proto udp
 +
 +log openvpn.log
 +verb 3
 +
 +ca /​etc/​openvpn/​ca.crt
 +cert /​etc/​openvpn/​my-client.crt
 +key /​etc/​openvpn/​my-client.key
 +
 +client
 +remote-cert-tls server
 +remote SERVER_IP_ADDRESS 1194
 +</​code>​
 +
 +===== Configure other clients (bridge)=====
 +Create the following OpenVPN client configuration file, save it with an ''​.ovpn''​ extension and give it to your client:
 +
 +<​code>​
 +dev tap
 +proto udp
 +
 +log openvpn.log
 +verb 3
 +
 +ca /​etc/​openvpn/​ca.crt
 +cert /​etc/​openvpn/​my-client.crt
 +key /​etc/​openvpn/​my-client.key
 +
 +client
 +remote-cert-tls server
 +remote SERVER_IP_ADDRESS 1194
 +</​code>​
 +
 +===== Test the tunnel =====
 +  - The tunnel should have made a change to the client'​s route table (so you can access the tunnel end-point, should be 10.8.0.1):<​code bash>
 +  cat /​tmp/​openvpn.log | grep "route add"
 +     ...
 +  route
 +</​code>​
 +  - You should be able to ping the tunnel end-point (i.e. the OpenVPN server):<​code bash>
 +  traceroute 10.8.0.1
 +</​code>​
 +  - You should still be able to ping hosts on the Internet via your default gateway:<​code bash>
 +  traceroute 8.8.8.8
 +</​code>​
 +  - You should be able to ping hosts on the Internet via the tunnel:<​code bash>
 +  route add -net 8.8.8.8 netmask 255.255.255.255 gateway 10.8.0.5
 +  route
 +     ...
 +  traceroute 8.8.8.8
 +</​code>​
 +
 +In particular, look at hops 1 and 2 of the **traceroute**;​ hop 1 should be one of the gateways from your route table. ​ If hop 2 of **traceroute 8.8.8.8** is the IP address of VPN_SERVER_ID,​ then the tunnel is working. ​
 +
 +:-D Congratulations! Now look to '​tune'​ the OpenVPN tunnel for a specific use-case.
 +
 +===== Route Only Local LAN Client Traffic Through the Tunnel =====
 +If all that is needed is to allow clients access to the local subnet (e.g., to access a server at home from work), and to leave Internet access as-is, all one needs to do is advertise the local subnet and configure the firewall to allow traffic through. First, to advertise the route:
 +
 +<code bash>
 +uci set openvpn.myvpn.push='​route 192.168.1.0 255.255.255.0'​
 +uci commit openvpn
 +/​etc/​init.d/​openvpn restart
 +</​code>​
 +
 +In this example the subnet is 192.168.1.0/​24. Adjust your configuration accordingly for your LAN. Now, the firewall has to be enabled to allow traffic from the VPN clients to the local LAN. To allow it, edit **/​etc/​config/​firewall**:​
 +
 +<​code>​
 +## NB: this zone should have already been created in the previous setup step; just add the masq option as noted below
 +config zone
 + option name '​vpn'​
 + option masq '​1'​ ## NB: this option was added to enable forwarding out of the VPN zone
 + option input '​ACCEPT'​
 + option forward '​ACCEPT'​
 + option output '​ACCEPT'​
 + option network '​vpn0'​
 +
 +## NB : this section was added
 +config forwarding
 + option src '​vpn'​
 + option dest '​lan'​
 +</​code>​
 +
 +After editing the firewall changes, enable them by executing:
 +<code bash>
 +/​etc/​init.d/​firewall reload
 +</​code>​
 +
 +===== Route All Client Traffic Through the Tunnel =====
 +If the OpenVPN server can access the Internet, then the client has the //option// of routing //all// its IP traffic via the tunnel rather than through it's local gateway. ​ If the tunnel is merely provide access to other subnets (e.g. to access a server at home from work), but Internet access is to remain as-is, then this is not your answer. ​ Instead, see [[doc/​howto/​vpn.openvpn#​route_only_local_lan_client_traffic_through_the_tunnel|Routing Only Local LAN Client Traffic Through the Tunnel]].
 +
 +Before you do this, you should know whether your network is **Scenario 1** (client and server in different subnets), or **Scenario 2** (client and server in the same subnet).  ​
 +
 +In **Scenario 1**, the client and server are in different subnets:
 +  - On the OpenVPN server, execute the following<​code bash>
 +  uci set openvpn.myvpn.push='​redirect-gateway def1' ​       ## NB: these are single quotes
 +  uci commit openvpn
 +  /​etc/​init.d/​openvpn restart
 +</​code>​
 +  - On the OpenVPN client, execute the following:<​code bash>
 +  /​etc/​init.d/​openvpn restart
 +  traceroute 8.8.8.8
 +</​code>​
 +
 +Alternatively,​ in **Scenario 2**, the client and server are in the same subnet (useful for creating/​testing an OpenVPN tunnel at home):
 +  - On the OpenVPN server, execute the following:<​code bash>
 +  uci set openvpn.myvpn.push='​redirect-gateway def1 local' ​ ## NB: these are single quotes
 +  uci commit openvpn; /​etc/​init.d/​openvpn restart
 +</​code>​
 +  - On the OpenVPN client, execute the following:<​code bash>
 +  /​etc/​init.d/​openvpn restart
 +  traceroute 8.8.8.8  ​
 +</​code>​
 +
 +:!: If your OpenVPN client is not to route all it's traffic via the server (and therefore continue to use it's existing default gateway), then you should not push the **redirect-gateway** option at all.
 +
 +You might need to make OpenWrt route traffic from vpn to wan. Add to /​etc/​config/​firewall:​
 +<​code>​
 +config forwarding
 + option src '​vpn'​
 + option dest '​wan'​
 +</​code>​
 +This worked for BB RC2 (uci commands would be better).
 +
 +Another way to accomplish routing all client traffic through the tunnel via LUCI is to navigate to Network -> Firewall and make the options look like this:
 +<​code>​
 +LAN: (lan: images) => VPN   : ​  ​accept accept accept (just changing this one to point to VPN instead of WAN)
 +WAN: (wan: images) => REJECT :  reject accept reject (no changes here)
 +VPN: (vpn: image) => WAN : accept accept accept (change forwarding to accept, check masquerading option)
 +</​code>​
 +
 +
 +Once this is working, head to [[doc/​howto/​vpn.server.openvpn.tun]] for more OpenVPN '​recipes'​.
 +
 +===== Troubleshooting =====
 +If something doesn'​t work as expected while following this HOWTO:
 +  * Check that the client can ping the server:<​code bash>​ping SERVER_IP_ADDRESS</​code>​
 +  * Check that the OpenVPN daemon is running:<​code bash>ps | grep "​openvpn"</​code>​
 +  * Check that there is a TUN interface:<​code bash>​ifconfig | grep "​tun"</​code>​
 +  * Check the log:<​code bash>cat /​tmp/​openvpn.log</​code>​
 +  * You can try temporarily disabling the firewall on the OpenVPN server:<​code bash>/​etc/​init.d/​firewall stop</​code>​
 +  * You can clear the OpenVPN configuration and start again from scratch:<​code bash>​echo > /​etc/​config/​openvpn</​code>​
 +
 +===== Asking for help =====
 +You can ask for help on the OpenWrt forum: [[https://​forum.openwrt.org/​]].  ​
 +
 +When asking for help, you should at a minimum include the contents of the following files:
 +<code bash>
 +cat /​tmp/​openvpn.log
 +cat /​etc/​config/​network
 +cat /​etc/​config/​firewall
 +cat /​etc/​config/​openvpn
 +</​code>​
 +
 +===== Caveats =====
 +
 +==== Client Config Dir ====
 +
 +When using UCI, you need to define the client config dir differently. All OpenVPN manuals tell you write it out as **client-config-dir** (with dashes), but for UCI you need to call it **client_config_dir** (with underscores). If unsure, check the openvpn conf file that is generated in /var/etc/, as that will have **client-config-dir** (with dashes) when all went well.
 +
 +===== References and examples =====
 +  * [[https://​community.openvpn.net/​openvpn/​wiki/​Openvpn23ManPage|OpenVPN 2.3 man-page]]
 +
 +===== Additions =====
 +You may create text config file, for example /​etc/​openvpn/​server,​ /​etc/​openvpn/​client and next include it in the openvpn instance in the /​etc/​config/​openvpn:​
 +<​code>​uci set openvpn.myvpnserver.config=/​etc/​openvpn/​myvpnserver.conf</​code>​
 +You may use included file and other tokens simultaneous,​ for example:
 +<​code>​
 +uci set openvpn.myvpnserverudp.config=/​etc/​openvpn/​common.conf
 +uci set openvpn.myvpnserverudp.proto=udp
 +uci set openvpn.myvpnservertcp.config=/​etc/​openvpn/​common.conf
 +uci set openvpn.myvpnservertcp.proto=tcp
 +
 +</​code>​
 +
 +| FIXME: Integrate any useful information from [[inbox:​vpn.howto]]. |
 +