Files
infix/dev/vpn-wireguard/index.html
T

3054 lines
66 KiB
HTML

<!DOCTYPE html><html lang="en" class="no-js"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Infix Documentation">
<link rel="canonical" href="https://kernelkit.github.io/infix/dev/vpn-wireguard/">
<link rel="prev" href="../vpn/">
<link rel="next" href="../wifi/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.7">
<title>WireGuard - User's Guide</title>
<link rel="stylesheet" href="../assets/stylesheets/main.ec1eaa64.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.ab4e12ef.min.css">
<link rel="stylesheet" href="../extra.css">
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<link href="../assets/stylesheets/glightbox.min.css" rel="stylesheet"><script src="../assets/javascripts/glightbox.min.js"></script><style id="glightbox-style">
html.glightbox-open { overflow: initial; height: 100%; }
.gslide-title { margin-top: 0px; user-select: text; }
.gslide-desc { color: #666; user-select: text; }
.gslide-image img { background: black; }
.glightbox-clean .gslide-media { -webkit-box-shadow: none; box-shadow: none; }
.gscrollbar-fixer { padding-right: 15px; }
.gdesc-inner { font-size: 0.75rem; }
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color); }
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color); }
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color); }
</style></head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="orange" data-md-color-accent="orange">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#wireguard-vpn" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<div data-md-color-scheme="default" data-md-component="outdated" hidden="">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="https://www.kernelkit.org/" title="User's Guide" class="md-header__button md-logo" aria-label="User's Guide" data-md-component="logo">
<img src="../logo-plain.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"></path></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
User's Guide
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
WireGuard
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="orange" data-md-color-accent="orange" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31"></path></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="orange" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden="">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z"></path></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required="">
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"></path></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"></path></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard="" data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"></path></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix="">
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/kernelkit/infix/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
kernelkit/infix
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="https://www.kernelkit.org/" title="User's Guide" class="md-nav__button md-logo" aria-label="User's Guide" data-md-component="logo">
<img src="../logo-plain.png" alt="logo">
</a>
User's Guide
</label>
<div class="md-nav__source">
<a href="https://github.com/kernelkit/infix/" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"></path></svg>
</div>
<div class="md-source__repository">
kernelkit/infix
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
CLI
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
CLI
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../cli/introduction/" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/configure/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/keybindings/" class="md-nav__link">
<span class="md-ellipsis">
Keybindings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/netcalc/" class="md-nav__link">
<span class="md-ellipsis">
Network Calculator
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/tcpdump/" class="md-nav__link">
<span class="md-ellipsis">
Network Monitoring
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/quick/" class="md-nav__link">
<span class="md-ellipsis">
Quickstart Guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/text-editor/" class="md-nav__link">
<span class="md-ellipsis">
Text Editor
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/upgrade/" class="md-nav__link">
<span class="md-ellipsis">
Upgrading
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../container/" class="md-nav__link">
<span class="md-ellipsis">
Docker Containers
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" checked="">
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Networking
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Networking
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../networking/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../iface/" class="md-nav__link">
<span class="md-ellipsis">
Common Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../bridging/" class="md-nav__link">
<span class="md-ellipsis">
Bridging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../lag/" class="md-nav__link">
<span class="md-ellipsis">
Link Aggregation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ethernet/" class="md-nav__link">
<span class="md-ellipsis">
Ethernet Interfaces
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vlan/" class="md-nav__link">
<span class="md-ellipsis">
VLAN Interfaces
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ip/" class="md-nav__link">
<span class="md-ellipsis">
IP Addressing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../routing/" class="md-nav__link">
<span class="md-ellipsis">
Routing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../firewall/" class="md-nav__link">
<span class="md-ellipsis">
Firewall Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../qos/" class="md-nav__link">
<span class="md-ellipsis">
Quality of Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../eth-counters/" class="md-nav__link">
<span class="md-ellipsis">
RMON Counters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tunnels/" class="md-nav__link">
<span class="md-ellipsis">
Tunneling (L2/L3)
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_13" checked="">
<label class="md-nav__link" for="__nav_4_13" id="__nav_4_13_label" tabindex="0">
<span class="md-ellipsis">
VPN Tunnels
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_13_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_4_13">
<span class="md-nav__icon md-icon"></span>
VPN Tunnels
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../vpn/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
WireGuard
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
WireGuard
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#key-management" class="md-nav__link">
<span class="md-ellipsis">
Key Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#point-to-point-configuration" class="md-nav__link">
<span class="md-ellipsis">
Point-to-Point Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#understanding-allowed-ips" class="md-nav__link">
<span class="md-ellipsis">
Understanding Allowed IPs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#peer-configuration-and-key-bags" class="md-nav__link">
<span class="md-ellipsis">
Peer Configuration and Key Bags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#site-to-site-vpn" class="md-nav__link">
<span class="md-ellipsis">
Site-to-Site VPN
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#road-warrior-vpn" class="md-nav__link">
<span class="md-ellipsis">
Road Warrior VPN
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hub-and-spoke-topology" class="md-nav__link">
<span class="md-ellipsis">
Hub-and-Spoke Topology
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#persistent-keepalive" class="md-nav__link">
<span class="md-ellipsis">
Persistent Keepalive
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ipv6-endpoints" class="md-nav__link">
<span class="md-ellipsis">
IPv6 Endpoints
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#monitoring-wireguard-status" class="md-nav__link">
<span class="md-ellipsis">
Monitoring WireGuard Status
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#post-quantum-security-preshared-keys" class="md-nav__link">
<span class="md-ellipsis">
Post-Quantum Security (Preshared Keys)
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../wifi/" class="md-nav__link">
<span class="md-ellipsis">
Wireless LAN (WiFi)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5">
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Services
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Services
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../discovery/" class="md-nav__link">
<span class="md-ellipsis">
Device Discovery
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../dhcp/" class="md-nav__link">
<span class="md-ellipsis">
DHCP Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ntp/" class="md-nav__link">
<span class="md-ellipsis">
NTP Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ptp/" class="md-nav__link">
<span class="md-ellipsis">
PTP (IEEE 1588/802.1AS)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6">
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
System
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
System
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../boot/" class="md-nav__link">
<span class="md-ellipsis">
Boot Procedure
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../system/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../nacm/" class="md-nav__link">
<span class="md-ellipsis">
Access Control (NACM)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../hardware/" class="md-nav__link">
<span class="md-ellipsis">
Hardware Info &amp; Status
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../management/" class="md-nav__link">
<span class="md-ellipsis">
Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../keystore/" class="md-nav__link">
<span class="md-ellipsis">
Keystore
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../syslog/" class="md-nav__link">
<span class="md-ellipsis">
Syslog Support
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../support/" class="md-nav__link">
<span class="md-ellipsis">
Support Data
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../upgrade/" class="md-nav__link">
<span class="md-ellipsis">
Upgrade
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7">
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Scripting
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Scripting
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../scripting/" class="md-nav__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-sysrepocfg/" class="md-nav__link">
<span class="md-ellipsis">
Legacy Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-netconf/" class="md-nav__link">
<span class="md-ellipsis">
NETCONF Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-restconf/" class="md-nav__link">
<span class="md-ellipsis">
RESTCONF Scripting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../scripting-prod/" class="md-nav__link">
<span class="md-ellipsis">
Production Testing
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8">
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="0">
<span class="md-ellipsis">
Developer's Corner
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Developer's Corner
</label>
<ul class="md-nav__list" data-md-scrollfix="">
<li class="md-nav__item">
<a href="../branding/" class="md-nav__link">
<span class="md-ellipsis">
Branding &amp; Releases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../developers-guide/" class="md-nav__link">
<span class="md-ellipsis">
Developer's Guide
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../override-package/" class="md-nav__link">
<span class="md-ellipsis">
Developing with Buildroot
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../netboot/" class="md-nav__link">
<span class="md-ellipsis">
Netboot HowTo
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../testing/" class="md-nav__link">
<span class="md-ellipsis">
Regression Testing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../test-arch/" class="md-nav__link">
<span class="md-ellipsis">
Test System Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../virtual/" class="md-nav__link">
<span class="md-ellipsis">
Virtual Environments
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../vpd/" class="md-nav__link">
<span class="md-ellipsis">
Vital Product Data (VPD)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../license/" class="md-nav__link">
<span class="md-ellipsis">
Origin &amp; Licensing
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix="">
<li class="md-nav__item">
<a href="#key-management" class="md-nav__link">
<span class="md-ellipsis">
Key Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#point-to-point-configuration" class="md-nav__link">
<span class="md-ellipsis">
Point-to-Point Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#understanding-allowed-ips" class="md-nav__link">
<span class="md-ellipsis">
Understanding Allowed IPs
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#peer-configuration-and-key-bags" class="md-nav__link">
<span class="md-ellipsis">
Peer Configuration and Key Bags
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#site-to-site-vpn" class="md-nav__link">
<span class="md-ellipsis">
Site-to-Site VPN
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#road-warrior-vpn" class="md-nav__link">
<span class="md-ellipsis">
Road Warrior VPN
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#hub-and-spoke-topology" class="md-nav__link">
<span class="md-ellipsis">
Hub-and-Spoke Topology
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#persistent-keepalive" class="md-nav__link">
<span class="md-ellipsis">
Persistent Keepalive
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#ipv6-endpoints" class="md-nav__link">
<span class="md-ellipsis">
IPv6 Endpoints
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#monitoring-wireguard-status" class="md-nav__link">
<span class="md-ellipsis">
Monitoring WireGuard Status
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#post-quantum-security-preshared-keys" class="md-nav__link">
<span class="md-ellipsis">
Post-Quantum Security (Preshared Keys)
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<nav class="md-path" aria-label="Navigation">
<ol class="md-path__list">
<li class="md-path__item">
<a href=".." class="md-path__link">
<span class="md-ellipsis">
Introduction
</span>
</a>
</li>
<li class="md-path__item">
<a href="../networking/" class="md-path__link">
<span class="md-ellipsis">
Networking
</span>
</a>
</li>
<li class="md-path__item">
<a href="../vpn/" class="md-path__link">
<span class="md-ellipsis">
VPN Tunnels
</span>
</a>
</li>
</ol>
</nav>
<article class="md-content__inner md-typeset">
<h1 id="wireguard-vpn">WireGuard VPN<a class="headerlink" href="#wireguard-vpn" title="Permanent link"></a></h1>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>For a general introduction to VPN concepts and deployment models, see
<a href="../vpn/">VPN Configuration</a>.</p>
</div>
<p>WireGuard is a modern, high-performance VPN protocol that uses state-of-the-art
cryptography. It is significantly simpler and faster than traditional VPN
solutions like IPsec or OpenVPN, while maintaining strong security guarantees.</p>
<p>Key features of WireGuard:</p>
<ul>
<li><strong>Simple Configuration:</strong> Minimal settings required compared to IPsec</li>
<li><strong>High Performance:</strong> Runs in kernel space with efficient cryptography</li>
<li><strong>Strong Cryptography:</strong> Uses Curve25519, ChaCha20, Poly1305, and BLAKE2</li>
<li><strong>Roaming Support:</strong> Seamlessly handles endpoint IP address changes</li>
<li><strong>Dual-Stack:</strong> Supports IPv4 and IPv6 for both tunnel endpoints and traffic</li>
</ul>
<div class="admonition tip">
<p class="admonition-title">Important</p>
<p>When issuing <code>leave</code> to activate your changes, remember to also save
your settings, <code>copy running-config startup-config</code>. See the <a href="../cli/introduction/">CLI
Introduction</a> for a background.</p>
</div>
<h2 id="key-management">Key Management<a class="headerlink" href="#key-management" title="Permanent link"></a></h2>
<p>WireGuard uses public-key cryptography similar to SSH. Each WireGuard interface
requires a private key, and each peer is identified by its public key.</p>
<p><strong>Import the key pair into the keystore:</strong></p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit keystore asymmetric-key wg-site-a</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/&gt; <b>do wireguard genkey</b>
Private: aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=
Public: bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=
admin@example:/config/keystore/asymmetric-key/wg-site-a/&gt; <b>set public-key-format x25519-public-key-format</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/&gt; <b>set private-key-format x25519-private-key-format</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/&gt; <b>set public-key bN1CwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP6KsrCwZ1lTP=</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/&gt; <b>set cleartext-private-key aMqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP5JrqBvZqkSP=</b>
admin@example:/config/keystore/asymmetric-key/wg-site-a/&gt; <b>leave</b>
admin@example:/&gt;
</code></pre>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>The <code>do</code> prefix allows running admin-exec commands from configure context.
Use the base for <code>wireguard genkey</code> when in admin-exec context.</p>
</div>
<p><strong>Import peer public keys into the truststore:</strong></p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit truststore public-key-bag wg-peers public-key peer-b</b>
admin@example:/config/truststore/…/peer-b/&gt; <b>set public-key-format x25519-public-key-format</b>
admin@example:/config/truststore/…/peer-b/&gt; <b>set public-key PEER_PUBLIC_KEY_HERE</b>
admin@example:/config/truststore/…/peer-b/&gt; <b>leave</b>
admin@example:/&gt;
</code></pre>
<div class="admonition tip">
<p class="admonition-title">Important</p>
<p>Keep private keys secure! Never share your private key. Only exchange
public keys with peers.</p>
</div>
<h2 id="point-to-point-configuration">Point-to-Point Configuration<a class="headerlink" href="#point-to-point-configuration" title="Permanent link"></a></h2>
<div class="admonition tip">
<p class="admonition-title">Tip</p>
<p>If you name your WireGuard interface <code>wgN</code>, where <code>N</code> is a number, the
CLI infers the interface type automatically.</p>
</div>
<p>A basic WireGuard tunnel between two sites:</p>
<p><strong>Site A configuration:</strong></p>
<pre class="cli"><code>admin@siteA:/&gt; <b>configure</b>
admin@siteA:/config/&gt; <b>edit interface wg0</b>
admin@siteA:/config/interface/wg0/&gt; <b>set wireguard listen-port 51820</b>
admin@siteA:/config/interface/wg0/&gt; <b>set wireguard private-key wg-site-a</b>
admin@siteA:/config/interface/wg0/&gt; <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
admin@siteA:/config/interface/wg0/&gt; <b>edit wireguard peer wg-peers peer-b</b>
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/&gt; <b>set endpoint 203.0.113.2</b>
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/&gt; <b>set endpoint-port 51820</b>
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/&gt; <b>set allowed-ips 10.0.0.2/32</b>
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/&gt; <b>set persistent-keepalive 25</b>
admin@siteA:/config/interface/…/wg-peers/peer/peer-b/&gt; <b>leave</b>
admin@siteA:/&gt;
</code></pre>
<p><strong>Site B configuration:</strong></p>
<pre class="cli"><code>admin@siteB:/&gt; <b>configure</b>
admin@siteB:/config/&gt; <b>edit interface wg0</b>
admin@siteB:/config/interface/wg0/&gt; <b>set wireguard listen-port 51820</b>
admin@siteB:/config/interface/wg0/&gt; <b>set wireguard private-key wg-site-b</b>
admin@siteB:/config/interface/wg0/&gt; <b>set ipv4 address 10.0.0.2 prefix-length 24</b>
admin@siteB:/config/interface/wg0/&gt; <b>edit wireguard peer wg-peers peer-a</b>
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/&gt; <b>set endpoint 203.0.113.1</b>
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/&gt; <b>set endpoint-port 51820</b>
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/&gt; <b>set allowed-ips 10.0.0.1/32</b>
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/&gt; <b>set persistent-keepalive 25</b>
admin@siteB:/config/interface/…/wg-peers/peer/peer-a/&gt; <b>leave</b>
admin@siteB:/&gt;
</code></pre>
<p>This creates an encrypted tunnel with Site A at 10.0.0.1 and Site B at 10.0.0.2.</p>
<h2 id="understanding-allowed-ips">Understanding Allowed IPs<a class="headerlink" href="#understanding-allowed-ips" title="Permanent link"></a></h2>
<p>The <code>allowed-ips</code> setting in WireGuard serves two critical purposes:</p>
<ol>
<li><strong>Ingress Filtering:</strong> Only packets with source IPs in the allowed list
are accepted from the peer</li>
<li><strong>Cryptokey Routing:</strong> Determines which peer receives outbound packets
for a given destination</li>
</ol>
<p>Think of <code>allowed-ips</code> as a combination of firewall rules and routing table.</p>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/wireguard-allowed-ips.svg" data-desc-position="bottom"><img alt="WireGuard Keys and Allowed IPs" src="../img/wireguard-allowed-ips.svg"></a>
<em>Figure: WireGuard key exchange and allowed-ips configuration between two peers</em></p>
<p>For a simple point-to-point tunnel, you typically allow only the peer's
tunnel IP address (e.g., <code>10.0.0.2/32</code>). For site-to-site VPNs connecting
entire networks, include the remote network prefixes:</p>
<pre class="cli"><code>admin@example:/config/interface/…/wg-peers/peer/peer-a/&gt; <b>set allowed-ips 10.0.0.2/32</b>
admin@example:/config/interface/…/wg-peers/peer/peer-a/&gt; <b>set allowed-ips 192.168.2.0/24</b>
</code></pre>
<p>This allows traffic to/from the peer at 10.0.0.2 and routes traffic destined
for 192.168.2.0/24 through this peer.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>When routing traffic to networks behind WireGuard peers, you also need
to configure static routes pointing to the WireGuard interface. See
<a href="../routing/">Static Routes</a> for more information.</p>
</div>
<h2 id="peer-configuration-and-key-bags">Peer Configuration and Key Bags<a class="headerlink" href="#peer-configuration-and-key-bags" title="Permanent link"></a></h2>
<p>WireGuard peer configuration supports a two-level hierarchy that allows
efficient management of multiple peers with shared settings.</p>
<p><strong>Public Key Bags</strong> group related peers together (e.g., all mobile clients,
all branch offices) and allow you to configure default settings that apply
to all peers in the bag. Individual peers can then override these defaults
when needed.</p>
<p>Settings that support bag-level defaults and per-peer overrides:</p>
<ul>
<li><code>endpoint</code> - Remote peer's IP address</li>
<li><code>endpoint-port</code> - Remote peer's UDP port (defaults to 51820 at bag level)</li>
<li><code>persistent-keepalive</code> - Keepalive interval in seconds</li>
<li><code>preshared-key</code> - Optional pre-shared key for additional quantum resistance</li>
<li><code>allowed-ips</code> - IP addresses allowed to/from this peer</li>
</ul>
<div class="admonition tip">
<p class="admonition-title">Important</p>
<p><strong>Key Bag Configuration Rules:</strong></p>
<ul>
<li>
<p><strong>Single key in bag:</strong> You can use bag-level settings (endpoint, allowed-ips, etc.)
without specifying individual peer configurations. All settings apply to that one peer.</p>
</li>
<li>
<p><strong>Multiple keys in bag:</strong> You MUST provide individual <code>peer</code> configuration for
each key in the bag. Settings like <code>endpoint</code> and <code>allowed-ips</code> must be unique
per peer and cannot be shared at the bag level when multiple peers exist.</p>
</li>
</ul>
<p>This prevents configuration errors where multiple peers would incorrectly share
the same endpoint address or allowed-ips ranges.</p>
</div>
<p><strong>Example with bag-level defaults:</strong></p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit interface wg0</b>
admin@example:/config/interface/wg0/&gt; <b>set wireguard listen-port 51820</b>
admin@example:/config/interface/wg0/&gt; <b>set wireguard private-key wg-key</b>
admin@example:/config/interface/wg0/&gt; <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
# Configure defaults for all peers in the 'branch-offices' bag
admin@example:/config/interface/wg0/&gt; <b>edit wireguard peers branch-offices</b>
admin@example:/config/interface/…/wireguard/peers/branch-offices/&gt; <b>set endpoint-port 51820</b>
admin@example:/config/interface/…/wireguard/peers/branch-offices/&gt; <b>set persistent-keepalive 25</b>
admin@example:/config/interface/…/wireguard/peers/branch-offices/&gt; <b>end</b>
# Configure peer-specific settings (inherits endpoint-port and keepalive from bag)
admin@example:/config/interface/…/wireguard/peers/branch-offices/&gt; <b>edit peer office-east</b>
admin@example:/config/interface/…/branch-offices/peer/office-east/&gt; <b>set endpoint 203.0.113.10</b>
admin@example:/config/interface/…/branch-offices/peer/office-east/&gt; <b>set allowed-ips 10.0.0.10/32</b>
admin@example:/config/interface/…/branch-offices/peer/office-east/&gt; <b>set allowed-ips 192.168.10.0/24</b>
admin@example:/config/interface/…/branch-offices/peer/office-east/&gt; <b>end</b>
# Another peer with an override for persistent-keepalive
admin@example:/config/interface/…/wireguard/peers/branch-offices/&gt; <b>edit peer office-west</b>
admin@example:/config/interface/…/branch-offices/peer/office-west/&gt; <b>set endpoint 203.0.113.20</b>
admin@example:/config/interface/…/branch-offices/peer/office-west/&gt; <b>set allowed-ips 10.0.0.20/32</b>
admin@example:/config/interface/…/branch-offices/peer/office-west/&gt; <b>set allowed-ips 192.168.20.0/24</b>
admin@example:/config/interface/…/branch-offices/peer/office-west/&gt; <b>set persistent-keepalive 10</b>
admin@example:/config/interface/…/branch-offices/peer/office-west/&gt; <b>leave</b>
admin@example:/&gt;
</code></pre>
<p>In this example:
- Both peers inherit <code>endpoint-port 51820</code> and <code>persistent-keepalive 25</code> from the bag
- <code>office-west</code> overrides the keepalive to 10 seconds while <code>office-east</code> uses the default 25
- Each peer has its own <code>endpoint</code> and <code>allowed-ips</code> configuration</p>
<p>This approach simplifies management when you have many peers with similar
configurations - set the common defaults once at the bag level, then only
specify per-peer differences.</p>
<h2 id="site-to-site-vpn">Site-to-Site VPN<a class="headerlink" href="#site-to-site-vpn" title="Permanent link"></a></h2>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/vpn-site-to-site.svg" data-desc-position="bottom"><img alt="Site-to-Site VPN Topology" src="../img/vpn-site-to-site.svg"></a>
<em>Figure: Site-to-Site VPN connecting two office networks</em></p>
<p>A site-to-site VPN connects entire networks across locations, creating a unified
private network over the internet. This allows devices in one location to
seamlessly access resources in another as if they were on the same local network.</p>
<p>This is the point-to-point configuration shown earlier, extended with routing
to allow access to networks behind each peer. Configure the WireGuard tunnel
as shown in <a href="#point-to-point-configuration">Point-to-Point Configuration</a>,
then add the remote network to <code>allowed-ips</code> and configure static routes.</p>
<h2 id="road-warrior-vpn">Road Warrior VPN<a class="headerlink" href="#road-warrior-vpn" title="Permanent link"></a></h2>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/vpn-roadwarrior.svg" data-desc-position="bottom"><img alt="Road Warrior VPN Topology" src="../img/vpn-roadwarrior.svg"></a>
<em>Figure: Mobile clients connecting to corporate network</em></p>
<p>For mobile clients or peers without fixed IPs, omit the <code>endpoint</code> setting.
WireGuard learns the peer's endpoint from authenticated incoming packets:</p>
<pre class="cli"><code>admin@hub:/&gt; <b>configure</b>
admin@hub:/config/&gt; <b>edit interface wg0 wireguard peers wg-peers peer mobile-client</b>
admin@hub:/config/interface/…/wg-peers/peer/mobile-client/&gt; <b>set allowed-ips 10.0.0.10/32</b>
admin@hub:/config/interface/…/wg-peers/peer/mobile-client/&gt; <b>leave</b>
admin@hub:/&gt;
</code></pre>
<p>The mobile client configures the hub's endpoint normally. The hub learns
and tracks the mobile client's changing IP address automatically.</p>
<h2 id="hub-and-spoke-topology">Hub-and-Spoke Topology<a class="headerlink" href="#hub-and-spoke-topology" title="Permanent link"></a></h2>
<p><a class="glightbox" data-type="image" data-width="100%" data-height="auto" href="../img/vpn-hub-spoke.svg" data-desc-position="bottom"><img alt="Hub-and-Spoke VPN Topology" src="../img/vpn-hub-spoke.svg"></a>
<em>Figure: Hub-and-Spoke topology with central hub routing traffic between spokes</em></p>
<p>WireGuard excels at hub-and-spoke (star) topologies where multiple remote
sites connect to a central hub.</p>
<p><strong>Hub configuration:</strong></p>
<pre class="cli"><code>admin@hub:/&gt; <b>configure</b>
admin@hub:/config/&gt; <b>edit interface wg0</b>
admin@hub:/config/interface/wg0/&gt; <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
admin@hub:/config/interface/wg0/&gt; <b>set wireguard listen-port 51820</b>
admin@hub:/config/interface/wg0/&gt; <b>set wireguard private-key wg-hub</b>
admin@hub:/config/interface/wg0/&gt; <b>edit wireguard peers wg-peers</b>
# Spoke 1
admin@hub:/config/interface/…/wireguard/peers/wg-peers/&gt; <b>edit peer spoke1</b>
admin@hub:/config/interface/…/wg-peers/peer/spoke1/&gt; <b>set allowed-ips 10.0.0.2/32</b>
admin@hub:/config/interface/…/wg-peers/peer/spoke1/&gt; <b>set allowed-ips 192.168.1.0/24</b>
admin@hub:/config/interface/…/wg-peers/peer/spoke1/&gt; <b>end</b>
# Spoke 2
admin@hub:/config/interface/…/wireguard/peers/wg-peers/&gt; <b>edit peer spoke2</b>
admin@hub:/config/interface/…/wg-peers/peer/spoke2/&gt; <b>set allowed-ips 10.0.0.3/32</b>
admin@hub:/config/interface/…/wg-peers/peer/spoke2/&gt; <b>set allowed-ips 192.168.2.0/24</b>
admin@hub:/config/interface/…/wg-peers/peer/spoke2/&gt; <b>leave</b>
# Add routes for spoke networks
admin@hub:/&gt; <b>configure</b>
admin@hub:/config/&gt; <b>edit routing control-plane-protocol static name default</b>
admin@hub:/config/routing/…/static/name/default/&gt; <b>set ipv4 route 192.168.1.0/24 wg0</b>
admin@hub:/config/routing/…/static/name/default/&gt; <b>set ipv4 route 192.168.2.0/24 wg0</b>
admin@hub:/config/routing/…/static/name/default/&gt; <b>leave</b>
admin@hub:/&gt;
</code></pre>
<p><strong>Spoke 1 configuration:</strong></p>
<pre class="cli"><code>admin@spoke1:/&gt; <b>configure</b>
admin@spoke1:/config/&gt; <b>edit interface wg0</b>
admin@spoke1:/config/interface/wg0/&gt; <b>set wireguard listen-port 51820</b>
admin@spoke1:/config/interface/wg0/&gt; <b>set wireguard private-key wg-spoke1</b>
admin@spoke1:/config/interface/wg0/&gt; <b>set ipv4 address 10.0.0.2 prefix-length 24</b>
admin@spoke1:/config/interface/wg0/&gt; <b>edit wireguard peers wg-peers peer hub</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>set endpoint 203.0.113.1</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>set endpoint-port 51820</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>set allowed-ips 10.0.0.1/32</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>set allowed-ips 10.0.0.3/32</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>set allowed-ips 192.168.0.0/24</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>set allowed-ips 192.168.2.0/24</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>set persistent-keepalive 25</b>
admin@spoke1:/config/interface/…/wg-peers/peer/hub/&gt; <b>leave</b>
admin@spoke1:/&gt; <b>configure</b>
admin@spoke1:/config/&gt; <b>edit routing control-plane-protocol static name default</b>
admin@spoke1:/config/routing/…/static/name/default/&gt; <b>set ipv4 route 192.168.0.0/24 wg0</b>
admin@spoke1:/config/routing/…/static/name/default/&gt; <b>set ipv4 route 192.168.2.0/24 wg0</b>
admin@spoke1:/config/routing/…/static/name/default/&gt; <b>leave</b>
admin@spoke1:/&gt;
</code></pre>
<p>This configuration allows Spoke 1 to reach both the hub network (192.168.0.0/24)
and Spoke 2's network (192.168.2.0/24) via the hub, enabling spoke-to-spoke
communication through the central hub.</p>
<h2 id="persistent-keepalive">Persistent Keepalive<a class="headerlink" href="#persistent-keepalive" title="Permanent link"></a></h2>
<p>The <code>persistent-keepalive</code> setting sends periodic packets to keep the tunnel
active through NAT devices and firewalls:</p>
<pre class="cli"><code>admin@example:/config/interface/…/wg-peers/peer/hub/&gt; <b>set persistent-keepalive 25</b>
</code></pre>
<p>This is particularly important when:</p>
<ul>
<li>The peer is behind NAT</li>
<li>Intermediate firewalls have connection timeouts</li>
<li>You need the tunnel to remain ready for bidirectional traffic</li>
</ul>
<p>A value of 25 seconds is recommended for most scenarios. Omit this setting
for peers with public static IPs that initiate connections.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Only the peer behind NAT needs <code>persistent-keepalive</code> configured. The
peer with a public IP learns the NAT endpoint from incoming packets.</p>
</div>
<h2 id="ipv6-endpoints">IPv6 Endpoints<a class="headerlink" href="#ipv6-endpoints" title="Permanent link"></a></h2>
<p>WireGuard fully supports IPv6 for tunnel endpoints:</p>
<pre class="cli"><code>admin@example:/&gt; <b>configure</b>
admin@example:/config/&gt; <b>edit interface wg0</b>
admin@example:/config/interface/wg0/&gt; <b>set wireguard listen-port 51820</b>
admin@example:/config/interface/wg0/&gt; <b>set wireguard private-key wg-key</b>
admin@example:/config/interface/wg0/&gt; <b>set ipv4 address 10.0.0.1 prefix-length 24</b>
admin@example:/config/interface/wg0/&gt; <b>set ipv6 address fd00::1 prefix-length 64</b>
admin@example:/config/interface/wg0/&gt; <b>edit wireguard peers wg-peers peer remote</b>
admin@example:/config/interface/…/wg-peers/peer/remote/&gt; <b>set endpoint 2001:db8::2</b>
admin@example:/config/interface/…/wg-peers/peer/remote/&gt; <b>set endpoint-port 51820</b>
admin@example:/config/interface/…/wg-peers/peer/remote/&gt; <b>set allowed-ips 10.0.0.2/32</b>
admin@example:/config/interface/…/wg-peers/peer/remote/&gt; <b>set allowed-ips fd00::2/128</b>
admin@example:/config/interface/…/wg-peers/peer/remote/&gt; <b>leave</b>
admin@example:/&gt;
</code></pre>
<p>WireGuard can carry both IPv4 and IPv6 traffic regardless of whether the
tunnel endpoints use IPv4 or IPv6.</p>
<h2 id="monitoring-wireguard-status">Monitoring WireGuard Status<a class="headerlink" href="#monitoring-wireguard-status" title="Permanent link"></a></h2>
<p>Check WireGuard interface status and peer connections:</p>
<pre class="cli"><code>admin@example:/&gt; <b>show interface</b>
wg0 wireguard UP 2 peers (1 up)
ipv4 10.0.0.1/24 (static)
ipv6 fd00::1/64 (static)
admin@example:/&gt; <b>show interface wg0</b>
name : wg0
type : wireguard
index : 12
operational status : up
peers : 2
Peer 1:
status : UP
endpoint : 203.0.113.2:51820
latest handshake : 2025-12-09T10:23:45+0000
transfer tx : 125648 bytes
transfer rx : 98432 bytes
Peer 2:
status : DOWN
endpoint : 203.0.113.3:51820
latest handshake : 2025-12-09T09:15:22+0000
transfer tx : 45120 bytes
transfer rx : 32768 bytes
</code></pre>
<p>The connection status shows <code>UP</code> if a handshake occurred within the last 3
minutes, indicating an active tunnel. The <code>latest handshake</code> timestamp shows
when the peers last successfully authenticated and exchanged keys.</p>
<h2 id="post-quantum-security-preshared-keys">Post-Quantum Security (Preshared Keys)<a class="headerlink" href="#post-quantum-security-preshared-keys" title="Permanent link"></a></h2>
<p>WireGuard supports optional preshared keys (PSK) that add an extra layer of
symmetric encryption alongside Curve25519. This provides defense-in-depth
against future quantum computers that might break elliptic curve cryptography.</p>
<p>PSKs protect your data from "harvest now, decrypt later" attacks - adversaries
recording traffic today would still need the PSK even if they break Curve25519
later. However, peer authentication still relies on Curve25519, so PSKs don't
provide complete post-quantum security.</p>
<p><strong>Generate a preshared key:</strong></p>
<pre class="cli"><code>admin@example:/config/&gt; <b>do wireguard genpsk</b>
cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=
</code></pre>
<p><strong>Import the preshared key into the keystore:</strong></p>
<pre class="cli"><code>admin@example:/config/&gt; <b>edit keystore symmetric-key wg-psk</b>
admin@example:/config/keystore/symmetric-key/wg-psk/&gt; <b>set key-format octet-string-key-format</b>
admin@example:/config/keystore/symmetric-key/wg-psk/&gt; <b>set cleartext-symmetric-key cO2DxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2mUQ7LtsrDxZ2m=</b>
admin@example:/config/keystore/symmetric-key/wg-psk/&gt; <b>end</b>
admin@example:/config/interface/wg0/&gt; <b>edit wireguard peers wg-peers peer remote</b>
admin@example:/config/interface/…/wg-peers/peer/remote/&gt; <b>set preshared-key wg-psk</b>
admin@example:/config/interface/…/wg-peers/peer/remote/&gt; <b>leave</b>
admin@example:/&gt;
</code></pre>
<p>The preshared key must be securely shared between both peers and configured
on both sides.</p>
<div class="admonition tip">
<p class="admonition-title">Important</p>
<p>Preshared keys must be kept secret and exchanged through a secure channel,
just like passwords.</p>
</div>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright © 2022-2026 The KernelKit Team
</div>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<div class="md-progress" data-md-component="progress" role="progressbar"></div>
<script id="__config" type="application/json">{"annotate": null, "base": "..", "features": ["toc.follow", "navigation.path", "navigation.instant", "navigation.instant.progress", "navigation.tracking", "navigation.indexes", "search.highlight", "search.share", "content.code.copy", "content.code.annotate", "content.footnote.tooltips"], "search": "../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"provider": "mike"}}</script>
<script src="../assets/javascripts/bundle.d7400e89.min.js"></script>
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
document$.subscribe(()=>{ lightbox.reload(); });
</script></body></html>