<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>VPN on KTDEVX</title><link>/en/tags/vpn/</link><description>KTDEVX (VPN)</description><generator>Hugo -- gohugo.io</generator><language>en</language><managingEditor>ktdevx@gmail.com
(Kaito Takemura)</managingEditor><lastBuildDate>Wed, 30 Apr 2025 23:28:18 +0900</lastBuildDate><atom:link href="/en/tags/vpn/index.xml" rel="self" type="application/rss+xml"/><item><title>Build an OpenVPN Server on OpenWrt for Remote Access to Your Home Network</title><link>/en/blog/set-up-a-vpn-server-on-openwrt-using-openvpn/</link><pubDate>Wed, 30 Apr 2025 23:28:18 +0900</pubDate><author>ktdevx@gmail.com (Kaito Takemura)</author><guid>/en/blog/set-up-a-vpn-server-on-openwrt-using-openvpn/</guid><description>&lt;p>OpenVPN is an open-source VPN technology that provides an encrypted VPN tunnel and secure access to your home network while away. This article explains how to build an OpenVPN server on an OpenWrt router and connect multiple clients.&lt;/p>
&lt;p>&lt;strong>Audience:&lt;/strong> Users with OpenWrt installed and SSH access&lt;br>
&lt;strong>Prerequisites:&lt;/strong> &lt;a href="https://www.ktdevx.com/en/blog/install-friendlywrt-on-nanopi-r2s/">OpenWrt installation&lt;/a>, administrator access, and basic terminal/SSH knowledge&lt;/p>
&lt;h2 id="environment" >
&lt;div>
&lt;a href="#environment">
#
&lt;/a>
Environment
&lt;/div>
&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Item&lt;/th>
&lt;th>Value&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>OS&lt;/td>
&lt;td>OpenWrt 24.10.0 or later&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>VPN protocol&lt;/td>
&lt;td>OpenVPN UDP 1194&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>VPN network&lt;/td>
&lt;td>10.8.0.0/24&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Encryption&lt;/td>
&lt;td>AES-128-CBC&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Authentication&lt;/td>
&lt;td>SHA256&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>CA validity&lt;/td>
&lt;td>3650 days (10 years)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Certificate validity&lt;/td>
&lt;td>825 days&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="install-the-packages" >
&lt;div>
&lt;a href="#install-the-packages">
#
&lt;/a>
Install the Packages
&lt;/div>
&lt;/h2>
&lt;p>Update the OpenWrt package list and install the OpenVPN packages.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>opkg update
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>opkg install openvpn-openssl openvpn-easy-rsa
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Package&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>openvpn-openssl&lt;/strong>&lt;/td>
&lt;td>Main OpenVPN package with SSL/TLS support&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>openvpn-easy-rsa&lt;/strong>&lt;/td>
&lt;td>Tool for generating and managing the CA and certificates&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>luci-app-openvpn&lt;/strong> (optional)&lt;/td>
&lt;td>Interface for managing OpenVPN in the LuCI web UI&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>luci-i18n-openvpn-ja&lt;/strong> (optional)&lt;/td>
&lt;td>Japanese OpenVPN localization for LuCI&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="set-the-environment-variables" >
&lt;div>
&lt;a href="#set-the-environment-variables">
#
&lt;/a>
Set the Environment Variables
&lt;/div>
&lt;/h2>
&lt;p>Edit &lt;code>/etc/profile.d/50-openvpn-easy-rsa.sh&lt;/code> in a text editor.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># default PKI dir&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export EASYRSA&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>EASYRSA&lt;span style="color:#66d9ef">:-&lt;/span>/etc/easy-rsa&lt;span style="color:#e6db74">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export EASYRSA_PKI&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>EASYRSA_PKI&lt;span style="color:#66d9ef">:-&lt;/span>$EASYRSA/pki&lt;span style="color:#e6db74">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export EASYRSA_VARS_FILE&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>EASYRSA_VARS_FILE&lt;span style="color:#66d9ef">:-&lt;/span>$EASYRSA/vars&lt;span style="color:#e6db74">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export EASYRSA_TEMP_DIR&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>EASYRSA_TEMP_DIR&lt;span style="color:#66d9ef">:-&lt;/span>&lt;span style="color:#e6db74">${&lt;/span>TMPDIR&lt;span style="color:#66d9ef">:-&lt;/span>/tmp/&lt;span style="color:#e6db74">}}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Save the file. The contents of profile.d are applied at login, so log in again or run &lt;code>. /etc/profile.d/50-openvpn-easy-rsa.sh&lt;/code> to apply the settings. This sets the Easy-RSA base directory and PKI path in the environment variables.&lt;/p>
&lt;h2 id="build-the-certificate-authority-ca" >
&lt;div>
&lt;a href="#build-the-certificate-authority-ca">
#
&lt;/a>
Build the Certificate Authority (CA)
&lt;/div>
&lt;/h2>
&lt;p>Build the CA with Easy-RSA&amp;rsquo;s &lt;code>build-ca&lt;/code> command.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# easyrsa build-ca
* Using Easy-RSA configuration:
/etc/easy-rsa/vars
* Using SSL: openssl OpenSSL 3.0.16 11 Feb 2025 (Library: OpenSSL 3.0.16 11 Feb 2025)
Enter New CA Key Passphrase:&amp;lt;passphrase&amp;gt;
Confirm New CA Key Passphrase:&amp;lt;passphrase-confirmation&amp;gt;
Using configuration from /tmp//2f994ff4/temp.5.1
...omitted...
Enter PEM pass phrase:&amp;lt;passphrase&amp;gt;
Verifying - Enter PEM pass phrase:&amp;lt;passphrase-confirmation&amp;gt;
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &amp;#39;.&amp;#39;, the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:&amp;lt;common-name&amp;gt;
Notice
------
CA creation complete. Your new CA certificate is at:
* /etc/easy-rsa/pki/ca.crt
&lt;/code>&lt;/pre>&lt;p>This creates the CA certificate &lt;code>ca.crt&lt;/code> in &lt;code>/etc/easy-rsa/pki&lt;/code> and the CA private key &lt;code>ca.key&lt;/code> in &lt;code>/etc/easy-rsa/pki/private/&lt;/code>. Copy the CA certificate to &lt;code>/etc/openvpn&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# cp /etc/easy-rsa/pki/ca.crt /etc/openvpn
&lt;/code>&lt;/pre>&lt;p>The CA setup is complete.&lt;/p>
&lt;h2 id="create-the-server-certificate-and-private-key" >
&lt;div>
&lt;a href="#create-the-server-certificate-and-private-key">
#
&lt;/a>
Create the Server Certificate and Private Key
&lt;/div>
&lt;/h2>
&lt;p>Generate the server certificate and key with Easy-RSA&amp;rsquo;s &lt;code>build-server-full&lt;/code> command. In this example, the server is named &lt;code>server&lt;/code>; &lt;code>nopass&lt;/code> is used because no passphrase is configured.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# easyrsa build-server-full &amp;lt;server-name&amp;gt; nopass
* Using Easy-RSA configuration:
/etc/easy-rsa/vars
* Using SSL: openssl OpenSSL 3.0.16 11 Feb 2025 (Library: OpenSSL 3.0.16 11 Feb 2025)
...omitted...
-----
Notice
------
Keypair and certificate request completed. Your files are:
* req: /etc/easy-rsa/pki/reqs/&amp;lt;server-name&amp;gt;.req
* key: /etc/easy-rsa/pki/private/&amp;lt;server-name&amp;gt;.key
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a server certificate
for &amp;#39;825&amp;#39; days:
subject=
commonName = &amp;lt;server-name&amp;gt;
Type the word &amp;#39;yes&amp;#39; to continue, or any other input to abort.
Confirm request details: yes
Using configuration from /tmp//d5a3377e/temp.4.1
Enter pass phrase for /etc/easy-rsa/pki/private/ca.key:&amp;lt;passphrase&amp;gt;
Check that the request matches the signature
Signature ok
The Subject&amp;#39;s Distinguished Name is as follows
commonName :ASN.1 12:&amp;#39;&amp;lt;server-name&amp;gt;&amp;#39;
Certificate is to be certified until Aug 4 09:43:06 2027 GMT (825 days)
Write out database with 1 new entries
Database updated
Notice
------
Certificate created at:
* /etc/easy-rsa/pki/issued/&amp;lt;server-name&amp;gt;.crt
Notice
------
Inline file created:
* /etc/easy-rsa/pki/inline/&amp;lt;server-name&amp;gt;.inline
&lt;/code>&lt;/pre>&lt;p>This creates the server certificate &lt;code>server.crt&lt;/code> in &lt;code>/etc/easy-rsa/pki/issued&lt;/code> and the server private key &lt;code>server.key&lt;/code> in &lt;code>/etc/easy-rsa/pki/private/&lt;/code>. Move them to &lt;code>/etc/openvpn&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# mv /etc/easy-rsa/pki/issued/server.crt /etc/easy-rsa/pki/private/server.key /etc/openvpn
&lt;/code>&lt;/pre>&lt;h2 id="generate-the-dh-parameters" >
&lt;div>
&lt;a href="#generate-the-dh-parameters">
#
&lt;/a>
Generate the DH Parameters
&lt;/div>
&lt;/h2>
&lt;p>Generate the random parameters required for encryption with Easy-RSA&amp;rsquo;s &lt;code>gen-dh&lt;/code> command.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# easyrsa gen-dh
* Using Easy-RSA configuration:
/etc/easy-rsa/vars
* Using SSL: openssl OpenSSL 3.0.16 11 Feb 2025 (Library: OpenSSL 3.0.16 11 Feb 2025)
Generating DH parameters, 2048 bit long safe prime
...omitted...
DH parameters appear to be ok.
Notice
------
DH parameters of size 2048 created at:
* /etc/easy-rsa/pki/dh.pem
&lt;/code>&lt;/pre>&lt;p>After a while, &lt;code>dh.pem&lt;/code> is created in &lt;code>/etc/easy-rsa/pki&lt;/code>. Move it to &lt;code>/etc/openvpn&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# mv /etc/easy-rsa/pki/dh.pem /etc/openvpn
&lt;/code>&lt;/pre>&lt;h2 id="generate-the-tls-auth-key" >
&lt;div>
&lt;a href="#generate-the-tls-auth-key">
#
&lt;/a>
Generate the TLS-Auth Key
&lt;/div>
&lt;/h2>
&lt;p>Generate a TLS-Auth key to use the TLS-Auth feature. It authenticates packets at the start of a VPN session with HMAC and discards unauthorized packets.&lt;/p>
&lt;pre tabindex="0">&lt;code>openvpn --genkey secret /etc/openvpn/ta.key
&lt;/code>&lt;/pre>&lt;p>This creates &lt;code>ta.key&lt;/code> in &lt;code>/etc/openvpn&lt;/code>.&lt;/p>
&lt;h2 id="create-the-server-configuration" >
&lt;div>
&lt;a href="#create-the-server-configuration">
#
&lt;/a>
Create the Server Configuration
&lt;/div>
&lt;/h2>
&lt;p>Create &lt;code>/etc/openvpn/server.conf&lt;/code> and configure routes for client connections.&lt;/p>
&lt;pre tabindex="0">&lt;code>port 1194
proto udp
dev tun
# SSL/TLS certificates and keys
ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key
dh /etc/openvpn/dh.pem
tls-auth /etc/openvpn/ta.key 0
# VPN client network
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /var/lib/openvpn/ipp.txt
# Push a route to the home network to VPN clients
push &amp;#34;route 192.168.1.0 255.255.255.0&amp;#34;
push &amp;#34;dhcp-option DNS 8.8.8.8&amp;#34;
push &amp;#34;dhcp-option DNS 8.8.4.4&amp;#34;
# Encryption and authentication
cipher AES-128-CBC
auth SHA256
tls-version-min 1.2
# Keepalive and logging
keepalive 10 120
user nobody
persist-key
persist-tun
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3
explicit-exit-notify 1
&lt;/code>&lt;/pre>&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Parameter&lt;/th>
&lt;th>Value&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>port&lt;/code>&lt;/td>
&lt;td>1194&lt;/td>
&lt;td>UDP port on which OpenVPN listens&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>proto&lt;/code>&lt;/td>
&lt;td>udp&lt;/td>
&lt;td>Protocol (UDP or TCP)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>dev&lt;/code>&lt;/td>
&lt;td>tun&lt;/td>
&lt;td>VPN tunnel device&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>server&lt;/code>&lt;/td>
&lt;td>10.8.0.0/24&lt;/td>
&lt;td>IP address range for VPN clients&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>push &amp;quot;route ...&amp;quot;&lt;/code>&lt;/td>
&lt;td>192.168.1.0/24&lt;/td>
&lt;td>Notifies clients of the route to the home LAN&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>push &amp;quot;dhcp-option DNS&amp;quot;&lt;/code>&lt;/td>
&lt;td>8.8.8.8&lt;/td>
&lt;td>DNS server used by clients&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>cipher&lt;/code>&lt;/td>
&lt;td>AES-128-CBC&lt;/td>
&lt;td>Encryption method&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>auth&lt;/code>&lt;/td>
&lt;td>SHA256&lt;/td>
&lt;td>HMAC authentication algorithm&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>tls-version-min&lt;/code>&lt;/td>
&lt;td>1.2&lt;/td>
&lt;td>Minimum TLS version&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>keepalive&lt;/code>&lt;/td>
&lt;td>10 120&lt;/td>
&lt;td>Sends keepalives every 10 seconds and considers the connection lost after 120 seconds without a response&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>user nobody&lt;/code>&lt;/td>
&lt;td>-&lt;/td>
&lt;td>Runs OpenVPN as an unprivileged user&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>persist-key&lt;/code>&lt;/td>
&lt;td>-&lt;/td>
&lt;td>Retains key files when restarting&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>persist-tun&lt;/code>&lt;/td>
&lt;td>-&lt;/td>
&lt;td>Retains the virtual interface when restarting&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>status&lt;/code>&lt;/td>
&lt;td>&lt;code>/var/log/openvpn-status.log&lt;/code>&lt;/td>
&lt;td>Log of connected clients&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>verb&lt;/code>&lt;/td>
&lt;td>3&lt;/td>
&lt;td>Log detail level&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="check-the-home-lan-address" >
&lt;div>
&lt;a href="#check-the-home-lan-address">
##
&lt;/a>
Check the Home LAN Address
&lt;/div>
&lt;/h3>
&lt;p>Change &lt;code>push &amp;quot;route 192.168.1.0 255.255.255.0&amp;quot;&lt;/code> to the address range of your home network. Check it with the following command.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>root@router:~# ip a
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Example output&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu &lt;span style="color:#ae81ff">1500&lt;/span> qdisc pfifo_fast state UP qlen &lt;span style="color:#ae81ff">1000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> inet 192.168.1.1/24 bcast 192.168.1.255 scope global eth0
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> valid_lft forever preferred_lft forever
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>In this example, the home LAN is &lt;code>192.168.1.0/24&lt;/code>. Replace it with the address used in your environment.&lt;/p>
&lt;h2 id="start-and-verify-the-openvpn-server" >
&lt;div>
&lt;a href="#start-and-verify-the-openvpn-server">
#
&lt;/a>
Start and Verify the OpenVPN Server
&lt;/div>
&lt;/h2>
&lt;p>Start OpenVPN after saving the server configuration.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>root@router:~# /etc/init.d/openvpn start
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# /etc/init.d/openvpn status
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>running
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# /etc/init.d/openvpn enable
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Check that port 1194 is listening.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>root@router:~# netstat -tlnup | grep &lt;span style="color:#ae81ff">1194&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Example output&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>udp &lt;span style="color:#ae81ff">0&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span> 0.0.0.0:1194 0.0.0.0:* 1234/openvpn
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>The setup is successful if the &lt;code>openvpn&lt;/code> process is listening on port 1194.&lt;/p>
&lt;h2 id="add-the-network-interface" >
&lt;div>
&lt;a href="#add-the-network-interface">
#
&lt;/a>
Add the Network Interface
&lt;/div>
&lt;/h2>
&lt;p>Check the tun device added by OpenVPN.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# ip a
...omitted...
12: tun0: &amp;lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&amp;gt; mtu 1500 qdisc fq_codel state UNKNOWN qlen 500
link/[65534]
inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::7ef9:4674:b626:2a37/64 scope link flags 800
valid_lft forever preferred_lft forever
...omitted...
&lt;/code>&lt;/pre>&lt;p>The device named &lt;code>tun0&lt;/code> has been added. Add it to the network interfaces as &lt;code>vpn&lt;/code> by appending the following to &lt;code>/etc/config/network&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code>config interface &amp;#39;vpn&amp;#39;
option proto &amp;#39;none&amp;#39;
option ifname &amp;#39;tun0&amp;#39;
&lt;/code>&lt;/pre>&lt;p>Restart the network.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# service network restart
&lt;/code>&lt;/pre>&lt;h2 id="configure-the-firewall" >
&lt;div>
&lt;a href="#configure-the-firewall">
#
&lt;/a>
Configure the Firewall
&lt;/div>
&lt;/h2>
&lt;p>Edit &lt;code>/etc/config/firewall&lt;/code>. Place the &lt;code>vpn&lt;/code> interface in the same zone as &lt;code>lan&lt;/code> by adding &lt;code>list network 'vpn'&lt;/code> to the &lt;code>lan&lt;/code> zone.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>config zone
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option name &lt;span style="color:#e6db74">&amp;#39;lan&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option input &lt;span style="color:#e6db74">&amp;#39;ACCEPT&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option output &lt;span style="color:#e6db74">&amp;#39;ACCEPT&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option forward &lt;span style="color:#e6db74">&amp;#39;ACCEPT&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> list network &lt;span style="color:#e6db74">&amp;#39;lan&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> list network &lt;span style="color:#e6db74">&amp;#39;vpn&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Add a rule to allow OpenVPN connections from &lt;code>wan&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>config rule
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option name &lt;span style="color:#e6db74">&amp;#39;Allow-OpenVPN&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option src &lt;span style="color:#e6db74">&amp;#39;wan&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option dest_port &lt;span style="color:#e6db74">&amp;#39;1194&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option proto &lt;span style="color:#e6db74">&amp;#39;udp&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> option target &lt;span style="color:#e6db74">&amp;#39;ACCEPT&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Restart the firewall.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# service firewall restart
&lt;/code>&lt;/pre>&lt;h2 id="create-a-client-certificate-and-private-key" >
&lt;div>
&lt;a href="#create-a-client-certificate-and-private-key">
#
&lt;/a>
Create a Client Certificate and Private Key
&lt;/div>
&lt;/h2>
&lt;p>Generate the client certificate and key with Easy-RSA&amp;rsquo;s &lt;code>build-client-full&lt;/code> command. In this example, the client is named &lt;code>client&lt;/code> and uses &lt;code>nopass&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code>root@router:~# easyrsa build-client-full &amp;lt;client-name&amp;gt; nopass
* Using Easy-RSA configuration:
/etc/easy-rsa/vars
* Using SSL: openssl OpenSSL 3.0.16 11 Feb 2025 (Library: OpenSSL 3.0.16 11 Feb 2025)
...omitted...
-----
Notice
------
Keypair and certificate request completed. Your files are:
* req: /etc/easy-rsa/pki/reqs/&amp;lt;client-name&amp;gt;.req
* key: /etc/easy-rsa/pki/private/&amp;lt;client-name&amp;gt;.key
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a client certificate
for &amp;#39;825&amp;#39; days:
subject=
commonName = &amp;lt;client-name&amp;gt;
Type the word &amp;#39;yes&amp;#39; to continue, or any other input to abort.
Confirm request details: yes
Using configuration from /tmp//23e0cc20/temp.4.1
Enter pass phrase for /etc/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject&amp;#39;s Distinguished Name is as follows
commonName :ASN.1 12:&amp;#39;&amp;lt;client-name&amp;gt;&amp;#39;
Certificate is to be certified until Aug 5 10:10:15 2027 GMT (825 days)
Write out database with 1 new entries
Database updated
Notice
------
Certificate created at:
* /etc/easy-rsa/pki/issued/&amp;lt;client-name&amp;gt;.crt
Notice
------
Inline file created:
* /etc/easy-rsa/pki/inline/&amp;lt;client-name&amp;gt;.inline
&lt;/code>&lt;/pre>&lt;p>This creates &lt;code>client.crt&lt;/code> in &lt;code>/etc/easy-rsa/pki/issued&lt;/code> and &lt;code>client.key&lt;/code> in &lt;code>/etc/easy-rsa/pki/private/&lt;/code>.&lt;/p>
&lt;h2 id="create-and-place-the-client-configuration" >
&lt;div>
&lt;a href="#create-and-place-the-client-configuration">
#
&lt;/a>
Create and Place the Client Configuration
&lt;/div>
&lt;/h2>
&lt;p>Create a client configuration file (&lt;code>.ovpn&lt;/code>) using the certificate and key generated by Easy-RSA.&lt;/p>
&lt;p>Copy the client files generated on the server to &lt;code>/tmp&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>root@router:~# cp /etc/easy-rsa/pki/issued/client.crt /tmp/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# cp /etc/easy-rsa/pki/private/client.key /tmp/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# cp /etc/openvpn/ca.crt /tmp/
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# cp /etc/openvpn/ta.key /tmp/
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create &lt;code>client.ovpn&lt;/code> with the following template.&lt;/p>
&lt;pre tabindex="0">&lt;code>client
dev tun
proto udp
remote &amp;lt;OpenWrt-global-IP-address&amp;gt; 1194
resolv-retry infinite
nobind
# Security settings
remote-cert-tls server
cipher AES-128-CBC
auth SHA256
tls-version-min 1.2
tls-auth ta.key 1
# Client logging
persist-key
persist-tun
verb 3
# CA certificate (inline)
&amp;lt;ca&amp;gt;
-----BEGIN CERTIFICATE-----
(Paste the contents of /etc/openvpn/ca.crt here)
-----END CERTIFICATE-----
&amp;lt;/ca&amp;gt;
# Client certificate (inline)
&amp;lt;cert&amp;gt;
-----BEGIN CERTIFICATE-----
(Paste the contents of /etc/easy-rsa/pki/issued/client.crt here)
-----END CERTIFICATE-----
&amp;lt;/cert&amp;gt;
# Client private key (inline)
&amp;lt;key&amp;gt;
-----BEGIN PRIVATE KEY-----
(Paste the contents of /etc/easy-rsa/pki/private/client.key here)
-----END PRIVATE KEY-----
&amp;lt;/key&amp;gt;
# TLS-Auth key
&amp;lt;tls-auth&amp;gt;
(Paste the contents of /etc/openvpn/ta.key here)
&amp;lt;/tls-auth&amp;gt;
&lt;/code>&lt;/pre>&lt;p>Display and copy each file&amp;rsquo;s contents on the server with the following commands.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>root@router:~# cat /etc/openvpn/ca.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# cat /etc/easy-rsa/pki/issued/client.crt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# cat /etc/easy-rsa/pki/private/client.key
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>root@router:~# cat /etc/openvpn/ta.key
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Paste each output into the corresponding section of the &lt;code>.ovpn&lt;/code> file.&lt;/p>
&lt;p>For a fixed global IP, use &lt;code>remote 203.0.113.1 1194&lt;/code>; for a dynamic IP, use a DDNS hostname such as &lt;code>remote example.ddns.jp 1194&lt;/code>.&lt;/p>
&lt;h2 id="test-connections-from-clients" >
&lt;div>
&lt;a href="#test-connections-from-clients">
#
&lt;/a>
Test Connections from Clients
&lt;/div>
&lt;/h2>
&lt;p>Transfer &lt;code>client.ovpn&lt;/code> to the client and test the connection.&lt;/p>
&lt;h3 id="linux-and-macos" >
&lt;div>
&lt;a href="#linux-and-macos">
##
&lt;/a>
Linux and macOS
&lt;/div>
&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># Ubuntu/Debian&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo apt install openvpn
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># macOS (Homebrew)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>brew install openvpn
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo openvpn --config client.ovpn
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>A successful connection displays &lt;code>Initialization Sequence Completed&lt;/code>. In another terminal, run &lt;code>ip a&lt;/code> and confirm &lt;code>tun0&lt;/code>, then use &lt;code>ping 192.168.1.1&lt;/code> to test routing to the home network. Press &lt;code>Ctrl+C&lt;/code> to disconnect.&lt;/p>
&lt;h3 id="windows" >
&lt;div>
&lt;a href="#windows">
##
&lt;/a>
Windows
&lt;/div>
&lt;/h3>
&lt;ol>
&lt;li>Download OpenVPN GUI from the &lt;a href="https://openvpn.net/download-open-vpn/">official OpenVPN download page&lt;/a> and install it with the default settings.&lt;/li>
&lt;li>Copy &lt;code>client.ovpn&lt;/code> to &lt;code>C:\Users\&amp;lt;username&amp;gt;\OpenVPN\config\&lt;/code>.&lt;/li>
&lt;li>Launch OpenVPN GUI, right-click its taskbar icon, select &lt;code>client.ovpn&lt;/code>, and select Connect.&lt;/li>
&lt;li>In PowerShell, run &lt;code>ipconfig&lt;/code> and confirm that a &lt;code>10.8.0.x&lt;/code> address was assigned to the TAP-Win32 Adapter for OpenVPN. Test with &lt;code>ping 192.168.1.1&lt;/code>.&lt;/li>
&lt;/ol>
&lt;h3 id="ios-and-android" >
&lt;div>
&lt;a href="#ios-and-android">
##
&lt;/a>
iOS and Android
&lt;/div>
&lt;/h3>
&lt;p>Install OpenVPN Connect from the App Store or Google Play, transfer &lt;code>client.ovpn&lt;/code> to the device, import it in the app, and tap the imported connection profile to connect.&lt;/p>
&lt;h2 id="troubleshooting" >
&lt;div>
&lt;a href="#troubleshooting">
#
&lt;/a>
Troubleshooting
&lt;/div>
&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Problem&lt;/th>
&lt;th>Cause&lt;/th>
&lt;th>Solution&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;strong>Timeout while connecting&lt;/strong>&lt;/td>
&lt;td>Insufficient firewall or router configuration&lt;/td>
&lt;td>Check the &lt;a href="https://www.ktdevx.com/en/blog/set-up-a-vpn-server-on-openwrt-using-openvpn/#configure-the-firewall">firewall configuration&lt;/a> and port forwarding&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Authentication error (TLS Handshake failed)&lt;/strong>&lt;/td>
&lt;td>Certificate or key mismatch&lt;/td>
&lt;td>Recheck the &lt;code>&amp;lt;ca&amp;gt;&lt;/code>, &lt;code>&amp;lt;cert&amp;gt;&lt;/code>, and &lt;code>&amp;lt;key&amp;gt;&lt;/code> sections&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>Cannot reach the home network&lt;/strong>&lt;/td>
&lt;td>Invalid &lt;code>push &amp;quot;route ...&amp;quot;&lt;/code> setting&lt;/td>
&lt;td>Confirm that the server&amp;rsquo;s &lt;code>push &amp;quot;route&amp;quot;&lt;/code> matches the home LAN address&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>DNS does not work&lt;/strong>&lt;/td>
&lt;td>DNS settings are not being sent&lt;/td>
&lt;td>Check &lt;code>push &amp;quot;dhcp-option DNS&amp;quot;&lt;/code> or configure DNS manually on the client&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;strong>No internet access after VPN connection&lt;/strong>&lt;/td>
&lt;td>Conflicting default route&lt;/td>
&lt;td>Add &lt;code>redirect-gateway def1&lt;/code> to &lt;code>client.ovpn&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Check server logs with &lt;code>tail -f /var/log/openvpn.log&lt;/code> and &lt;code>cat /var/log/openvpn-status.log&lt;/code>. For verbose client logs, use &lt;code>--verb 4&lt;/code> with OpenVPN.&lt;/p>
&lt;h2 id="dynamic-ip-support-ddns" >
&lt;div>
&lt;a href="#dynamic-ip-support-ddns">
#
&lt;/a>
Dynamic IP Support (DDNS)
&lt;/div>
&lt;/h2>
&lt;p>If the OpenWrt external IP address changes, use DDNS so clients can connect by hostname.&lt;/p>
&lt;p>&lt;a href="https://www.ktdevx.com/en/blog/automatically-update-dns-records-for-onamae-com-from-openwrt-with-ddns-using-ddns-scripts-onamae/">Automatically Update DNS Records on OpenWrt with DDNS&lt;/a>&lt;/p>
&lt;p>Change the &lt;code>remote&lt;/code> parameter to the DDNS hostname.&lt;/p>
&lt;pre tabindex="0">&lt;code># Before (global IP address)
remote 203.0.113.1 1194
# After (DDNS hostname)
remote myhome.ddns.jp 1194
&lt;/code>&lt;/pre>&lt;h2 id="security-recommendations" >
&lt;div>
&lt;a href="#security-recommendations">
#
&lt;/a>
Security Recommendations
&lt;/div>
&lt;/h2>
&lt;h3 id="renew-certificates-regularly" >
&lt;div>
&lt;a href="#renew-certificates-regularly">
##
&lt;/a>
Renew Certificates Regularly
&lt;/div>
&lt;/h3>
&lt;p>Generated certificates are valid for 825 days. Generate and deploy new certificates regularly.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>openssl x509 -in /etc/openvpn/server.crt -noout -text | grep -A2 &lt;span style="color:#e6db74">&amp;#34;Validity&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="check-firewall-settings" >
&lt;div>
&lt;a href="#check-firewall-settings">
##
&lt;/a>
Check Firewall Settings
&lt;/div>
&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># UFW&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo ufw allow 1194/udp
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"># iptables&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo iptables -A INPUT -p udp --dport &lt;span style="color:#ae81ff">1194&lt;/span> -j ACCEPT
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="add-pam-authentication-optional" >
&lt;div>
&lt;a href="#add-pam-authentication-optional">
##
&lt;/a>
Add PAM Authentication (Optional)
&lt;/div>
&lt;/h3>
&lt;p>To add password authentication, add the following to &lt;code>server.conf&lt;/code>.&lt;/p>
&lt;pre tabindex="0">&lt;code>auth-user-pass-verify /etc/openvpn/checkpsw.sh via-env
script-security 3
username-as-common-name
&lt;/code>&lt;/pre>&lt;h2 id="related-articles-and-external-links" >
&lt;div>
&lt;a href="#related-articles-and-external-links">
#
&lt;/a>
Related Articles and External Links
&lt;/div>
&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://openwrt.org/docs/guide_user/services/vpn/openvpn/server">OpenVPN installation on OpenWrt (official documentation)&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://openwrt.org/docs/guide_user/services/vpn/openvpn/start">OpenWrt Wiki - OpenVPN&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.ktdevx.com/en/blog/install-friendlywrt-on-nanopi-r2s/">OpenWrt installation&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.ktdevx.com/en/blog/set-up-a-vpn-server-on-openwrt-using-wireguard-to-access-the-home-network-from-outside/">Build a VPN server with WireGuard&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.ktdevx.com/en/blog/automatically-update-dns-records-for-onamae-com-from-openwrt-with-ddns-using-ddns-scripts-onamae/">Configure DDNS on OpenWrt&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.ktdevx.com/en/blog/generate-ssh-key/">How to generate an SSH key&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.openssl.org/docs/">OpenSSL documentation&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38A.pdf">NIST cryptographic recommendations&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>