User Tools

Site Tools


OpenVPN Dual Stack


  • The guide describes how to install and configure OpenWrt with OpenVPN server as a dual stack gateway.
  • We try to keep balance between security and simplicity, making an emphasis on privacy and automation.
  • There're all the necessary workarounds for tunnel connectivity, private network routing and masquerading.
  • It helps to generate OpenVPN client profile as a single file easy to export/import between devices.


  • You want to escape internet censorship and prevent traffic spoofing.
  • Your client-ISP does not provide dual stack connectivity or public IP-addresses.
  • You want to connect to your private network services without port forwarding.


  • Client dual stack connectivity even when your client-ISP does not support it.
  • Client dual stack privacy including DNS-privacy.



1. Preparation

Install OpenWrt and configure interfaces WAN and WAN6.

2. Network

Add default IPv6-route for VPN-traffic. Create VPN-interface.

source /lib/functions/
network_find_wan6 NET_IF
network_get_gateway6 NET_GW "$NET_IF"
uci add network route6
uci set network.@route6[-1].interface="$NET_IF"
uci set network.@route6[-1].target="::/0"
uci set network.@route6[-1].gateway="$NET_GW"
uci set network.vpnserver="interface"
uci set network.vpnserver.ifname="tun0"
uci set network.vpnserver.proto="none"
uci commit network
service network restart

3. Firewall

Consider VPN-network as trusted and assign it to LAN-zone. Otherwise create a separate zone with appropriate policy. Allow access to OpenVPN server from WAN-zone.

uci add_list firewall.@zone[0].network="vpnserver"
uci add firewall rule
uci set firewall.@rule[-1].name="Allow-OpenVPN"
uci set firewall.@rule[-1].src="wan"
uci set firewall.@rule[-1].dest_port="1194"
uci set firewall.@rule[-1].proto="udp"
uci set firewall.@rule[-1].target="ACCEPT"
uci commit firewall
service firewall restart

4. NAT6

Request IPv6-pool from your server-ISP to skip NAT6-configuration. Otherwise use firewall script populating NAT6-table from NAT4-table dump.

opkg update
opkg install kmod-ipt-nat6
cat << "EOF" > /etc/firewall.user
iptables-save --table="nat" \
| sed -e "/ [DS]NAT /d" \
| ip6tables-restore --table="nat"
uci set firewall.@include[0].reload="1"
uci commit firewall
service firewall restart

5. PKI

Use Easy-RSA for PKI-management. Advanced parameters may require launching OpenSSL directly.

opkg install openvpn-easy-rsa
export EASYRSA="/etc/easy-rsa"
easyrsa --batch init-pki
easyrsa --batch gen-dh
easyrsa --batch --req-cn="vpnca" build-ca nopass
easyrsa --batch build-server-full "vpnserver" nopass
easyrsa --batch build-client-full "vpnclient1" nopass
easyrsa --batch build-client-full "vpnclient2" nopass

6. OpenVPN Server

Configure OpenVPN server. Replace private IPv6-pool with public one obtained from your server-ISP.

opkg install openvpn-openssl
openvpn --genkey --secret "$EASYRSA_PKI/tc.pem"
uci set openvpn.vpnserver="openvpn"
uci set openvpn.vpnserver.enabled="1"
uci set openvpn.vpnserver.verb="3"
uci set"tun0"
uci set openvpn.vpnserver.topology="subnet"
uci set openvpn.vpnserver.port="1194"
uci set openvpn.vpnserver.proto="udp"
uci set openvpn.vpnserver.server=""
uci set openvpn.vpnserver.server_ipv6="fdf1:7610:d152:3a9c::/64"
uci set openvpn.vpnserver.keepalive="10 120"
uci set openvpn.vpnserver.persist_tun="1"
uci set openvpn.vpnserver.persist_key="1"
uci set openvpn.vpnserver.dh="$EASYRSA_PKI/dh.pem"
uci set openvpn.vpnserver.tls_crypt="$EASYRSA_PKI/tc.pem"
uci set"$EASYRSA_PKI/ca.crt"
uci set openvpn.vpnserver.cert="$EASYRSA_PKI/issued/vpnserver.crt"
uci set openvpn.vpnserver.key="$EASYRSA_PKI/private/vpnserver.key"
uci add_list openvpn.vpnserver.push="redirect-gateway def1 ipv6"
uci add_list openvpn.vpnserver.push="dhcp-option DOMAIN $(uci get dhcp.@dnsmasq[0].domain)"
uci add_list openvpn.vpnserver.push="dhcp-option DNS $(uci get openvpn.vpnserver.server_ipv6 | sed -e "s/\/.*$/1/")"
uci add_list openvpn.vpnserver.push="persist-tun"
uci add_list openvpn.vpnserver.push="persist-key"
uci commit openvpn
service openvpn restart

7. OpenVPN Client

Generate OpenVPN client configurations. Download backup from OpenWrt web-interface, extract client profiles from the archive and import them to your clients. Remove Windows-specific options block from non-Windows clients.

source /lib/functions/
network_find_wan NET_IF
network_get_ipaddr SERVER_ADDR "$NET_IF"
SERVER_PORT="$(uci get openvpn.vpnserver.port)"
SERVER_PROTO="$(uci get openvpn.vpnserver.proto)"
CLIENT_DEV="$(uci get | sed -e "s/\d*$//")"
TC_KEY="$(sed -e "/^#/d;/^\w/N;s/\n//" "$EASYRSA_PKI/tc.pem")"
CA_CERT="$(openssl x509 -in "$EASYRSA_PKI/ca.crt")"
NETSH_IPV6="C:\\\\Windows\\\\System32\\\\cmd.exe /c netsh interface ipv6"
grep -r -l -e "TLS Web Client Authentication" "$EASYRSA_PKI/issued" \
| sed -e "s/^.*\///;s/\.[^.]*$//" \
| while read CLIENT_ID
CLIENT_CERT="$(openssl x509 -in "$EASYRSA_PKI/issued/$CLIENT_ID.crt")"
CLIENT_KEY="$(cat "$EASYRSA_PKI/private/$CLIENT_ID.key")"
cat << EOF > "$CLIENT_CONF"
# <windows dns-leak-fix tun6-connectivity-fix>
script-security 2
up '$NETSH_IPV6 set privacy state=disabled store=active & echo'
ipchange '$NETSH_IPV6 set global randomizeidentifiers=disabled store=active & echo'
route-up '$NETSH_IPV6 delete route prefix=%ifconfig_ipv6_local%/%ifconfig_ipv6_netbits% interface=%dev_idx% store=active'
# </windows>
verb 3
remote-cert-tls server
chmod 600 "$CLIENT_CONF"

8. Tests

Request IPv6-pool and delegate it to your VPN-network to pass Browser-Default-IPv6 and Browser-Fallback-IPv4 tests. Make sure there are no client-ISP DNS-servers in the DNS-Leak test results.

9. Diagnostics

service log restart; service openvpn restart
sleep 10; logread -e openvpn; pgrep -f -a openvpn
ip -4 a; ip -4 r; ip -4 ru; iptables-save
ip -6 a; ip -6 r; ip -6 ru; ip6tables-save
uci show network; uci show firewall; uci show openvpn


docs/guide-user/services/vpn/openvpn/dual_stack.txt · Last modified: 2018/12/16 13:33 by vgaetera