{"id":738,"date":"2025-01-01T12:31:04","date_gmt":"2025-01-01T07:01:04","guid":{"rendered":"https:\/\/vihaaniotgateway.in\/?p=738"},"modified":"2025-09-28T23:33:22","modified_gmt":"2025-09-28T18:03:22","slug":"ultimate-guide-to-installing-and-configuring-openvpn-on-freebsd-13-4-for-a-secure-vpn-connection","status":"publish","type":"post","link":"https:\/\/vihaaniotgateway.in\/index.php\/2025\/01\/01\/ultimate-guide-to-installing-and-configuring-openvpn-on-freebsd-13-4-for-a-secure-vpn-connection\/","title":{"rendered":"Ultimate Guide to Installing and Configuring OpenVPN on FreeBSD 13.4 for a Secure VPN Connection"},"content":{"rendered":"\n<p id=\"880e\"><em>In this article, we will guide you through setting up your own VPN. If you have a public IP, you can set it up on a BeagleBone Black. Alternatively, if you don\u2019t have a public IP, you can deploy the VPN on an AWS t4g.micro instance. For AWS deployments, it\u2019s recommended to use an Elastic IP to prevent IP changes when the instance is stopped. We will cover the AWS instance deployment process separately.<\/em><\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"2d25\">Setup server on Beaglebone black<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"f84d\">Please make sure you have listed items ready<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>Beaglebone black.<\/em><\/li>\n\n\n\n<li><em>5v power supply or Mini-USB cable.<\/em><\/li>\n\n\n\n<li><em>Micro-SDHC card 16GB or larger.<\/em><\/li>\n\n\n\n<li><em>Serial cable such as Adafruit #954 or FTDI TTL232R-3V3 (optional but highly recommended).<\/em><\/li>\n\n\n\n<li>BalenaEtcher installed on windows<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"3115\">Install FreeBSD 13.4 Image on BeagleBone Black<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Download FreeBSD-13.4-RELEASE-arm-armv7-GENERICSD.img from&nbsp;freebsd website.<\/li>\n\n\n\n<li>Use BalenaEtcher to write the image to SD card<\/li>\n\n\n\n<li>Insert SD card and boot from SD card. Here I am assuming user knows how to boot new image from SD card and get ssh working. Please follow this link to Flash Image on SD card https:\/\/vihaaniotgateway.in\/index.php\/2025\/01\/19\/setting-up-freebsd-on-beaglebone-black-an-easy-installation-guide\/<\/li>\n\n\n\n<li>Connect Beaglebone black to LAN and login through ssh<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"6d5e\">Setup OpenVPn server on Beaglebone black\/AWS t4g.micro instance<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install OpenVPN on Your Server<\/li>\n\n\n\n<li>Configure OpenVPN Server Settings<\/li>\n\n\n\n<li>Set Up PKI and Configure Environment Variables for EasyRSA<\/li>\n\n\n\n<li>Generate Server Certificates for Secure Connection<\/li>\n\n\n\n<li>Create Client Certificates for VPN Access<\/li>\n\n\n\n<li>Configure OpenVPN Server Settings<\/li>\n\n\n\n<li>Enable IP Forwarding for Network Traffic Routing<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"30ad\"><strong>Install OpenVPN on Your Server<\/strong><\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\">pkg install -y openvpn;<br>mkdir -p \/usr\/local\/etc\/openvpn;<br>cp \/usr\/local\/share\/examples\/openvpn\/sample-config-files\/server.conf \/usr\/local\/etc\/openvpn\/openvpn.conf;<br>mkdir -p \/usr\/local\/etc\/openvpn\/easy-rsa;<br>cp -r  \/usr\/local\/share\/easy-rsa\/* \/usr\/local\/etc\/openvpn\/easy-rsa;<br> <\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"4520\">Set Up PKI and Configure Environment Variables for EasyRSA<\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/usr\/local\/etc\/openvpn\/easy-rsa<br>easyrsa init-pki<br>vi \/usr\/local\/etc\/openvpn\/easy-rsa\/vars<br>set_var EASYRSA_REQ_COUNTRY     \"&lt; &gt;\"<br>set_var EASYRSA_REQ_PROVINCE    \"&lt; &gt;\"<br>set_var EASYRSA_REQ_CITY        \"&lt; &gt;\"<br>set_var EASYRSA_REQ_ORG         \"&lt;Your Organization Name&gt;\"<br>set_var EASYRSA_REQ_EMAIL       \"&lt;Your Email&gt;\"<br>set_var EASYRSA_REQ_OU          \"&lt;use your public ip or host name&gt;\"<br>set_var EASYRSA_KEY_SIZE         2048<br>set_var EASYRSA_CA_EXPIRE        3650<br>set_var EASYRSA_CERT_EXPIRE     3650<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"960d\"><strong>Generate Server Certificates for Secure Connection<\/strong><\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\">easyrsa build-ca nopass<br>easyrsa build-server-full openvpn-server nopass<br>easyrsa gen-dh<br>mkdir -p \/usr\/local\/etc\/openvpn\/keys;<br>cd \/usr\/local\/etc\/openvpn;<br>cp -p easy-rsa\/pki\/ca.crt keys\/ca.crt;<br>cp -p easy-rsa\/pki\/dh.pem keys\/dh.pem;<br>cp -p easy-rsa\/pki\/issued\/openvpn-server.crt keys\/openvpn-server.crt;<br>cp -p easy-rsa\/pki\/private\/openvpn-server.key keys\/openvpn-server.key;<br>cd \/usr\/local\/etc\/openvpn\/keys;<br>openvpn --genkey secret ta.key;<br>sysrc openvpn_enable=\"YES\";<br>sysrc openvpn_if=\"tun\";<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"1ff8\"><strong>Configure OpenVPN Server Settings<\/strong><\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\">We are using tcp port 80 because it would be easy to migrate to AWS. There is only one (external n\/w interface)difference <br>between aws and beagle bone black. All steps would be same except pf rules and instance deployement,<br><br>cat oprnvpn.conf.patch<br>--- \/usr\/local\/etc\/openvpn\/openvpn.conf.orig    2024-12-22 14:10:58.899905000 +0000<br>+++ \/usr\/local\/etc\/openvpn\/openvpn.conf 2024-12-22 14:40:56.878042000 +0000<br>@@ -29,11 +29,12 @@<br> # on the same machine, use a different port<br> # number for each one.  You will need to<br> # open up this port on your firewall.<br>-port 1194<br>+;port 1194<br>+port 80<br><br> # TCP or UDP server?<br>-;proto tcp<br>-proto udp<br>+proto tcp<br>+;proto udp<br><br> # \"dev tun\" will create a routed IP tunnel,<br> # \"dev tap\" will create an ethernet tunnel.<br>@@ -83,14 +84,18 @@ dev tun<br> # and use the peer-fingerprint option.<br> # See openvpn-examples man page for a<br> # configuration example.<br>-ca ca.crt<br>-cert server.crt<br>-key server.key  # This file should be kept secret<br>+;ca ca.crt<br>+;cert server.crt<br>+;key server.key  # This file should be kept secret<br>+ca \/usr\/local\/etc\/openvpn\/keys\/ca.crt<br>+cert \/usr\/local\/etc\/openvpn\/keys\/openvpn-server.crt<br>+key \/usr\/local\/etc\/openvpn\/keys\/openvpn-server.key<br>+dh \/usr\/local\/etc\/openvpn\/keys\/dh.pem<br><br> # Diffie hellman parameters.<br> # Generate your own with:<br> #   openssl dhparam -out dh2048.pem 2048<br>-dh dh2048.pem<br>+;dh dh2048.pem<br><br> # Allow to connect to really old OpenVPN versions<br> # without AEAD support (OpenVPN 2.3.x or older)<br>@@ -112,7 +117,8 @@ topology subnet<br> # Each client will be able to reach the server<br> # on 10.8.0.1. Comment this line out if you are<br> # ethernet bridging. See the man page for more info.<br>-server 10.8.0.0 255.255.255.0<br>+;server 10.8.0.0 255.255.255.0<br>+server 172.16.100.0 255.255.255.0<br><br> # Maintain a record of client &lt;-&gt; virtual IP address<br> # associations in this file.  If OpenVPN goes down or<br>@@ -220,7 +226,7 @@ ifconfig-pool-persist ipp.txt<br> # To force clients to only see the server, you<br> # will also need to appropriately firewall the<br> # server's TUN\/TAP interface.<br>-;client-to-client<br>+client-to-client<br><br> # Uncomment this directive if multiple clients<br> # might connect with the same certificate\/key<br>@@ -233,7 +239,7 @@ ifconfig-pool-persist ipp.txt<br> # CERTIFICATE\/KEY PAIRS FOR EACH CLIENT,<br> # EACH HAVING ITS OWN UNIQUE \"COMMON NAME\",<br> # UNCOMMENT THIS LINE.<br>-;duplicate-cn<br>+duplicate-cn<br><br> # The keepalive directive causes ping-like<br> # messages to be sent back and forth over<br>@@ -268,7 +274,8 @@ keepalive 10 120<br> # systems after creating a dedicated user.<br> ;user openvpn<br> ;group openvpn<br>-<br>+user nobody<br>+group nobody<br> # The persist options will try to avoid<br> # accessing certain resources on restart<br> # that may no longer be accessible because<br>@@ -307,4 +314,4 @@ verb 3<br><br> # Notify the client that when the server restarts so it<br> # can automatically reconnect.<br>-explicit-exit-notify 1<br>\\ No newline at end of file<br>+explicit-exit-notify 1<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"3a4d\"><strong><strong>Enable IP Forwarding for Network Traffic Routing<\/strong><\/strong><\/h1>\n\n\n\n<p id=\"bcb7\">This is needed if you want your internet traffic route through vpn tunnel, otherwise vpn connected devices won\u2019t be able to reach to internet. I am not sure if there is a better way to do this, I was able to make it work by using this approach. Once openvpn is up then you should see tun0 interface up. The screenshot is taken from aws t4g.micro instance. On Beaglebone black also it would look similar except it will display cpsw0 instead of ena0 for externel interface.<\/p>\n\n\n\n<p id=\"4749\">service openvpn status<br>openvpn is running as pid 804.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"564\" src=\"https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-1024x564.png\" alt=\"\" class=\"wp-image-749\" srcset=\"https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-1024x564.png 1024w, https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-300x165.png 300w, https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-768x423.png 768w, https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-600x330.png 600w, https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image.png 1068w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<pre class=\"wp-block-preformatted\">echo 'pf<em>_load=\"YES\"' &gt;&gt; \/boot\/loader.conf<br>echo 'net.inet.ip.forwarding=1' &gt;&gt; \/etc\/sysctl.conf<br><strong>****<\/strong><strong>****<\/strong><strong>**For AWS Instance Only**<\/strong><strong>****<\/strong><strong>****<\/strong><strong>****<\/strong><strong>****<\/strong><strong>****<\/strong><strong>****<\/strong><br>echo 'nat on ena0 from 172.16.100.0\/24 to any -&gt; (ena0)' &gt; \/etc\/pf.conf<br><strong>****<\/strong><strong>****<\/strong><strong>****<\/strong><strong>**For BeagleBone Black Only**<\/strong><strong>****<\/strong><strong>****<\/strong><strong>****<\/strong><strong>****<\/strong>*<br>echo 'nat on cpsw0 from 172.16.100.0\/24 to any -&gt; (cpsw0)' &gt; \/etc\/pf.conf<br>sysrc pf_<\/em>enable=\"YES\"<br>sysrc gateway<em>_enable=\"YES\"<br>reboot<\/em><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"a6b6\"><strong>Create Client Certificates for VPN Access<\/strong><\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/usr\/local\/etc\/openvpn\/easy-rsa;<br>easyrsa build-client-full openvpn-aws-client nopass;<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"04aa\">Connect Client On Windows 11<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install OpenVpn Connect For Windows<\/li>\n\n\n\n<li>Create .ovpn file and write this data<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-preformatted\">client<br>dev tun<br>proto tcp<br>remote aws\/beaglebone-black-public-ip 80<br>persist-key<br>persist-tun<br>redirect-gateway def1<br>&lt;ca&gt;<br>-----BEGIN CERTIFICATE-----<br>Replace with the ca data  cat \/usr\/local\/etc\/openvpn\/keys\/ca.crt<br>-----END CERTIFICATE-----<br>&lt;\/ca&gt;<br>&lt;cert&gt;<br>-----BEGIN CERTIFICATE-----<br>Replace with cert cat \/usr\/local\/etc\/openvpn\/easy-rsa\/pki\/issued\/openvpn-aws-client.crt<br>-----END CERTIFICATE-----<br>&lt;\/cert&gt;<br>&lt;key&gt;<br>Replace with client key cat \/usr\/local\/etc\/openvpn\/easy-rsa\/pki\/private\/openvpn-aws-client.key<br>&lt;\/key&gt;<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"4d1d\">Import Profile in OpenVpn Connect App<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Install OpenVpn Connect For Windows<\/li>\n\n\n\n<li>Import above created .ovpn file<\/li>\n\n\n\n<li>Click on connect, you should be able to connect to vpn<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"376\" height=\"580\" src=\"https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-1.png\" alt=\"\" class=\"wp-image-751\" srcset=\"https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-1.png 376w, https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-1-194x300.png 194w\" sizes=\"(max-width: 376px) 100vw, 376px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"556\" height=\"757\" src=\"https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-2.png\" alt=\"\" class=\"wp-image-752\" srcset=\"https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-2.png 556w, https:\/\/vihaaniotgateway.in\/wordpress\/wp-content\/uploads\/2025\/01\/image-2-220x300.png 220w\" sizes=\"(max-width: 556px) 100vw, 556px\" \/><\/figure>\n\n\n\n<p id=\"1db2\">Steps to deploy aws t4g.micro instance To be continued \u2026<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p id=\"af67\">Issues faced and References:<\/p>\n<\/blockquote>\n\n\n\n<p id=\"e398\">Initially I struggled to make internet work on vpn connected devices and found that only pf configuration and ip forwarding made it work. I added this in Beaglebone black configuration openvpn.conf but looks like it is not required as today I configured without this on aws without these changes.<\/p>\n\n\n\n<p id=\"708a\"># To assign specific IP addresses to specific<br>@@ -204,6 +208,7 @@ ifconfig-pool-persist ipp.txt<br># or bridge the TUN\/TAP interface to the internet<br># in order for this to work properly).<br>;push \u201credirect-gateway def1 bypass-dhcp\u201d<br>+push \u201credirect-gateway def1\u201d<\/p>\n\n\n\n<p id=\"bdb3\"># Certain Windows-specific network settings<br># can be pushed to clients, such as DNS<br>@@ -213,6 +218,8 @@ ifconfig-pool-persist ipp.txt<br># DNS servers provided by opendns.com.<br>;push \u201cdhcp-option DNS 208.67.222.222\u201d<br>;push \u201cdhcp-option DNS 208.67.220.220\u201d<br>+push \u201cdhcp-option DNS 8.8.8.8\u201d<br>+push \u201cdhcp-option DNS 8.8.4.4\u201d<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we will guide you through setting up your own VPN. If you have a public IP, you can set it up on a BeagleBone Black. Alternatively, if you don\u2019t have a public IP, you can deploy the VPN on an AWS t4g.micro instance. For AWS deployments, it\u2019s recommended to use an Elastic [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[27],"tags":[],"class_list":["post-738","post","type-post","status-publish","format-standard","hentry","category-freebsd"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/posts\/738","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/comments?post=738"}],"version-history":[{"count":10,"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/posts\/738\/revisions"}],"predecessor-version":[{"id":2009,"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/posts\/738\/revisions\/2009"}],"wp:attachment":[{"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/media?parent=738"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/categories?post=738"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vihaaniotgateway.in\/index.php\/wp-json\/wp\/v2\/tags?post=738"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}