URI: 
       wireguard.html - www.codemadness.org - www.codemadness.org saait content files
  HTML git clone git://git.codemadness.org/www.codemadness.org
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       wireguard.html (11462B)
       ---
            1 <!DOCTYPE html>
            2 <html dir="ltr" lang="en">
            3 <head>
            4         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            5         <meta http-equiv="Content-Language" content="en" />
            6         <meta name="viewport" content="width=device-width" />
            7         <meta name="keywords" content="Wireguard, OpenBSD, VPN, wg, mobile, Android" />
            8         <meta name="description" content="Guide to setup a Wireguard endpoint on OpenBSD to use as a (mobile) VPN" />
            9         <meta name="author" content="Hiltjo" />
           10         <meta name="generator" content="Static content generated using saait: https://codemadness.org/saait.html" />
           11         <title>Wireguard on OpenBSD for use as a mobile VPN - Codemadness</title>
           12         <link rel="stylesheet" href="style.css" type="text/css" media="screen" />
           13         <link rel="stylesheet" href="print.css" type="text/css" media="print" />
           14         <link rel="alternate" href="atom.xml" type="application/atom+xml" title="Codemadness Atom Feed" />
           15         <link rel="alternate" href="atom_content.xml" type="application/atom+xml" title="Codemadness Atom Feed with content" />
           16         <link rel="icon" href="/favicon.png" type="image/png" />
           17 </head>
           18 <body>
           19         <nav id="menuwrap">
           20                 <table id="menu" width="100%" border="0">
           21                 <tr>
           22                         <td id="links" align="left">
           23                                 <a href="index.html">Blog</a> |
           24                                 <a href="/git/" title="Git repository with some of my projects">Git</a> |
           25                                 <a href="/releases/">Releases</a> |
           26                                 <a href="gopher://codemadness.org">Gopherhole</a>
           27                         </td>
           28                         <td id="links-contact" align="right">
           29                                 <span class="hidden"> | </span>
           30                                 <a href="feeds.html">Feeds</a> |
           31                                 <a href="pgp.asc">PGP</a> |
           32                                 <a href="mailto:hiltjo@AT@codemadness.DOT.org">Mail</a>
           33                         </td>
           34                 </tr>
           35                 </table>
           36         </nav>
           37         <hr class="hidden" />
           38         <main id="mainwrap">
           39                 <div id="main">
           40                         <article>
           41 <header>
           42         <h1>Wireguard on OpenBSD for use as a mobile VPN</h1>
           43         <p>
           44         <strong>Last modification on </strong> <time>2026-05-30</time>
           45         </p>
           46 </header>
           47 
           48 <p>Wireguard is a fast, modern and secure VPN tunnel.</p>
           49 <p>Below is a guide to setup <a href="https://www.wireguard.com/">Wireguard</a> on the OpenBSD
           50 operating system intended for use as a mobile VPN.</p>
           51 <p>It describes using the OpenBSD Wireguard wg(4) kernel driver using ifconfig,
           52 not the userland application, and will focus on setting up a IPv4 tunnel.</p>
           53 <p>It is however recommended to install wireguard-tools, because it contains
           54 useful tools to generate a private and public key (wg genkey, wg pubkey).</p>
           55 <p>To install the wireguard-tools package on OpenBSD:</p>
           56 <pre><code># pkg_add wireguard-tools
           57 </code></pre>
           58 <h2>Enable IPv4 traffic forwarding</h2>
           59 <p>To enable traffic forwarding for IPv4 run:</p>
           60 <pre><code># sysctl net.inet.ip.forwarding=1
           61 </code></pre>
           62 <p>To make it persistent add the above lines to the file /etc/sysctl.conf.  These
           63 sysctl lines are loaded on boot time.</p>
           64 <h2>Server config: /etc/hostname.wg0</h2>
           65 <p>This is an example config for the wg0 network interface.  It is stored at
           66 /etc/hostname.wg0:</p>
           67 <pre><code>wgport 51820 wgkey 'private_key_here'
           68 inet 10.1.2.1/24
           69 up
           70 
           71 # peer: phone
           72 wgpeer 'pubkey_here' wgaip 10.1.2.2/32 wgdescr 'phone' wgpsk 'psk_here'
           73 </code></pre>
           74 <h2>Generating a private key</h2>
           75 <p>Using wireguard-tools wg command:</p>
           76 <pre><code>$ wg genkey
           77 </code></pre>
           78 <p>Replace private_key_here with the generated text.</p>
           79 <p>To generate both a private and public key to the files private.key and
           80 public.key:</p>
           81 <pre><code>$ wg genkey | tee private.key | wg pubkey &gt; public.key
           82 </code></pre>
           83 <p><strong>!!! Keep the private key secure. Do not share it with anyone!!!</strong></p>
           84 <h2>Generate a separate preshared key (PSK).</h2>
           85 <p>Using a preshared key (PSK) is optional, but recommended. This is used in the
           86 handshake to guard against future compromise of the peers' encrypted tunnel if
           87 a quantum-computational attack on their Diffie-Hellman exchange becomes
           88 feasible.</p>
           89 <p>Using wireguard-tools wg command:</p>
           90 <pre><code>$ wg genpsk
           91 </code></pre>
           92 <p>The PSK can be shared with a known client when configuring the clients. <strong>Make sure
           93 to share it via a safe channel</strong>.</p>
           94 <p>To configure or restart the wg0 interface using the configuration in
           95 /etc/hostname.wg0:</p>
           96 <pre><code># sh /etc/netstart wg0
           97 </code></pre>
           98 <p>To show general info of the interface run the command (requires root
           99 permissions to view all information):</p>
          100 <pre><code># ifconfig wg0
          101 </code></pre>
          102 <p>In the ifconfig wg0 output it should list the server public key as:</p>
          103 <pre><code>wgpubkey server_pubkey_here
          104 </code></pre>
          105 <h2>Full example of a client config: wg-client.conf</h2>
          106 <pre><code>[Interface]
          107 Address = 10.1.2.2/32
          108 DNS = 10.1.2.1
          109 PrivateKey = CHBzstIHCi7+YOOa2MN0RXhkPAmJwIXQW0e6/n6+Pno=
          110 
          111 [Peer]
          112 AllowedIPs = 0.0.0.0/0
          113 Endpoint = example.org:51820
          114 PreSharedKey = 8ao/EMExyPAHrT3ShX+lnA0u7jUmo7MhrT0GjDcrIJA=
          115 PublicKey = Rny+AW4EPqPPxfO+8O+QdlkIrWbZRGQ6u6Fje5pUOFM=
          116 </code></pre>
          117 <p><strong>Of course do not copy-paste this private key and PSK. Generate your own ;)</strong></p>
          118 <h2>pf(4) firewall rules</h2>
          119 <p>Below is a fragment of the firewall rules required for Wireguard.
          120 These rules assume a simple VPS with a vio network interface connected to the
          121 interwebs (no double NAT or other weird complex things ;)).</p>
          122 <p>pf.conf:</p>
          123 <pre><code># wireguard
          124 pass out quick on egress inet from (wg0:network) nat-to (vio0:0)
          125 pass in quick on wg0 from any to any
          126 pass in quick on wg0 proto udp from any to any port 51820
          127 # allow all on wireguard
          128 pass quick on wg0
          129 </code></pre>
          130 <h2>Mobile VPN application</h2>
          131 <p>For Android download the APK from <a href="https://www.wireguard.com/install/">https://www.wireguard.com/install/</a>.
          132 There are also other versions available on the page.</p>
          133 <h2>Android Wireguard settings</h2>
          134 <h2>Adding a tunnel</h2>
          135 <p>In the Wireguard application press the plus (+) button in the bottom left of
          136 the screen to add a tunnel.</p>
          137 <h2>Option: "Scan from QR code"</h2>
          138 <h3>Generate a QR code image from a client config</h3>
          139 <p>Install the libqrencode package for the qrencode program:</p>
          140 <pre><code># pkg_add libqrencode
          141 </code></pre>
          142 <p>Generate a QR code PNG image from a client config:</p>
          143 <pre><code>$ qrencode -o qr.png &lt; wg-client.conf
          144 </code></pre>
          145 <p>This QR code simply contains the full text from the wg-client.conf. It can be
          146 scanned from the Android Wireguard application.  If it contains sensitive
          147 information such as the private key make sure to share the image in a safe way
          148 and/or destroy it immediately.</p>
          149 <p><img src="downloads/openbsd-wg/client-example-qr.png" alt="QR code image" /></p>
          150 <p>If the QR code contains a private key, make sure to destroy it "Inspector Gadget"-style.</p>
          151 <p><img src="downloads/openbsd-wg/inspector_gadget.jpg" alt="inspector Gadget reading self-destruct message" width="320" height="240" loading="lazy" /></p>
          152 <p><a href="downloads/openbsd-wg/inspector_gadget.webm">Inspector Gadget, self-destruct video clip</a></p>
          153 <p>Now scan the generated image to import the config.</p>
          154 <h3>Option: "Import from file or archive"</h3>
          155 <p>Import a text .conf file or archive (ZIP) file containing one or more configs.</p>
          156 <p>Example conf file: <a href="downloads/openbsd-wg/client-example.conf">client-example.conf</a>.<br />  
          157 Example ZIP file: <a href="downloads/openbsd-wg/client-example.zip">client-example.zip</a>.</p>
          158 <h3>Option: "Create from scratch"</h3>
          159 <p>Generating the private key on the device itself and sharing the <strong>public</strong> key
          160 and PSK is probably the safest option.  Although sharing the public key text
          161 from a mobile device can be a bit annoying.</p>
          162 <h2>Android settings</h2>
          163 <p>Only allow connections and DNS using VPN:</p>
          164 <ul>
          165 <li>Settings -&gt; VPN -&gt; Network &amp; Internet:
          166 Make sure Wireguard is set and enabled under VPN.</li>
          167 </ul>
          168 <p>VPN settings, open Wireguard cogwheel:
          169 <ul>
          170 <li>Enable: Always on VPN option, with the description: "Stay connected to VPN at all times".</li>
          171 <li>Enable: Block connections without VPN.</li>
          172 </ul>
          173 </p>
          174 <p>Other recommendations:</p>
          175 <ul>
          176 <li>Under Wi-Fi -&gt; Privacy.
          177 <ul>
          178 <li>Use randomized MAC.</li>
          179 <li>Disable "Send device name".</li>
          180 </ul>
          181 </li>
          182 <li>Set a secure and privacy-respecting DNS server.</li>
          183 </ul>
          184 <h2>Wireguard persistent keepalive setting</h2>
          185 <p>If the interface very rarely sends traffic, but it might at anytime receive
          186 traffic from a peer, and it is behind NAT, the interface might benefit from
          187 having a persistent keepalive interval of 25 seconds.</p>
          188 <p>If it is not needed, then it is recommended to not enable it, which is the
          189 default.</p>
          190 <p>This option is called PersistentKeepalive in Wireguard conf and is called
          191 wgpka for OpenBSD ifconfig, see the ifconfig(8) man page WIREGUARD section.</p>
          192 <h2>Debugging tips</h2>
          193 <p>For the Wireguard Android application you can find a textual log:</p>
          194 <ul>
          195 <li>Open the Wireguard application.</li>
          196 <li>At the top right select the 3 dots settings thingy.</li>
          197 <li>Select the menu labeled "View application log".</li>
          198 </ul>
          199 <p>On the OpenBSD server you can run enable run-time debugging on the wg0 interface:</p>
          200 <pre><code># ifconfig wg0 debug
          201 </code></pre>
          202 <h2>Bonus: example using wg-quick from wg-tools</h2>
          203 <p>Using the wg-quick program from wg-tools you can also quickly setup a client.
          204 This will setup the DNS, routing and interface. It can setup and restore the
          205 DNS and routing settings easily.</p>
          206 <p>As root, to setup the interface:</p>
          207 <pre><code># wg-quick up absolute/path/to/config/wg-client.conf
          208 </code></pre>
          209 <p>As root, to restore the interface:</p>
          210 <pre><code># wg-quick down absolute/path/to/config/wg-client.conf
          211 </code></pre>
          212 <h2>Bonus: generating a private key using only OpenSSL commands</h2>
          213 <p>Generate a private key:</p>
          214 <pre><code>$ openssl genpkey -algorithm X25519 -outform DER -out private.der
          215 </code></pre>
          216 <p>Now extract the last 32 bytes which has part of the actual private key (the
          217 first ASN.1 DER encoded bytes contain metadata information). Convert the actual
          218 key data to base64.</p>
          219 <p>Run:</p>
          220 <pre><code>$ tail -c 32 private.der | openssl enc -a -A &gt; private.key
          221 </code></pre>
          222 <p>Derive public key:</p>
          223 <pre><code>$ openssl pkey -inform DER -in private.der -pubout -outform DER -out public.der
          224 </code></pre>
          225 <p>Convert public key to Wireguard format:</p>
          226 <pre><code>$ tail -c 32 public.der | openssl enc -a -A &gt; public.key
          227 </code></pre>
          228 <p>Or even the magical voodoo commands:</p>
          229 <pre><code>$ openssl rand -base64 32 &gt; private.key
          230 $ (printf '\060\056\002\001\000\060\005\006\003\053\145\156\004\042\004\040';openssl enc -d -a -A &lt; private.key) | \
          231   openssl pkey -inform DER -pubout -outform DER | \
          232         tail -c 32 | \
          233         openssl enc -a -A &gt; public.key
          234 </code></pre>
          235 <h2>References</h2>
          236 <ul>
          237 <li><a href="https://www.wireguard.com/">Wireguard</a>:
          238 <ul>
          239 <li><a href="https://www.wireguard.com/quickstart/">Wireguard quickstart page</a>:
          240 This uses the userland Wireguard programs and config. But it contains
          241 helpful information.<br />  </li>
          242 <li><a href="https://www.man7.org/linux/man-pages/man8/wg.8.html">wg(8) man page</a>.</li>
          243 <li><a href="https://www.man7.org/linux/man-pages/man8/wg-quick.8.html">wg-quick(8) man page</a>.</li>
          244 </ul>
          245 </li>
          246 <li><a href="https://www.openbsd.org/">OpenBSD operating system</a>:
          247 <ul>
          248 <li><a href="https://man.openbsd.org/wg">wg(4) driver man page</a>.</li>
          249 <li><a href="https://man.openbsd.org/ifconfig.8#WIREGUARD">ifconfig(8) man page WIREGUARD section</a>.</li>
          250 <li><a href="https://man.openbsd.org/pf.conf.5">pf.conf(5) file format</a>.</li>
          251 </ul>
          252 </li>
          253 </ul>
          254 
          255                         </article>
          256                 </div>
          257         </main>
          258 </body>
          259 </html>