This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
wireguard [2025/12/03 14:08] djgalloway [How To] |
wireguard [2025/12/17 18:25] (current) dmick [Mac/Linux] |
||
|---|---|---|---|
| Line 4: | Line 4: | ||
| ===== How To ===== | ===== How To ===== | ||
| + | |||
| + | Overall flow: | ||
| + | * install Wireguard | ||
| + | * generate a public/private keypair; | ||
| + | * send in the public key to David/Dan to get a server entry | ||
| + | * get an IP address to use in return | ||
| + | * use the private key, the IP address, and these instructions to configure your | ||
| + | client | ||
| + | |||
| + | ==== Mac/Linux == | ||
| 1. For Mac, Install Wireguard from the App Store\\ | 1. For Mac, Install Wireguard from the App Store\\ | ||
| Line 10: | Line 20: | ||
| For Linux,\\ | For Linux,\\ | ||
| <code> | <code> | ||
| - | sudo apt install wireguard-tools | + | sudo apt install wireguard-tools resolvconf |
| # or | # or | ||
| sudo dnf install wireguard-tools | sudo dnf install wireguard-tools | ||
| </code> | </code> | ||
| - | 2. Install ''wireguard-tools'' using [[https://brew.sh/|Homebrew]]\\ | + | For Mac, install ''wireguard-tools'' using [[https://brew.sh/|Homebrew]]\\ |
| <code> | <code> | ||
| brew install wireguard-tools | brew install wireguard-tools | ||
| Line 26: | Line 36: | ||
| 4. Generate a keypair | 4. Generate a keypair | ||
| + | |||
| <code> | <code> | ||
| wg genkey | tee ~/.wireguard/private.key | wg pubkey > ~/.wireguard/public.key | wg genkey | tee ~/.wireguard/private.key | wg pubkey > ~/.wireguard/public.key | ||
| Line 32: | Line 43: | ||
| **Keep the Private Key secret!!** | **Keep the Private Key secret!!** | ||
| - | 5. Send the public.key contents to David or Dan. They will update the Wireguard server and give you your VPN IP address. | + | 5. Send the Wireguard public key (''~/.wireguard/public.key'' contents) to David or Dan. They will update the Wireguard server and give you your VPN IP address. |
| - | 6. Create ''~/.wireguard/client.conf''\\ | + | 6. Create ''~/.wireguard/client.conf'' (note that the $PRIVATE_KEY must expand to |
| + | the actual text of your private key)\\ | ||
| <code> | <code> | ||
| PRIVATE_KEY=$(cat ~/.wireguard/private.key) | PRIVATE_KEY=$(cat ~/.wireguard/private.key) | ||
| Line 43: | Line 55: | ||
| Address = X.X.X.X/32 | Address = X.X.X.X/32 | ||
| DNS = 10.20.192.11, front.sepia.ceph.com, ipmi.sepia.ceph.com | DNS = 10.20.192.11, front.sepia.ceph.com, ipmi.sepia.ceph.com | ||
| + | MTU = 1200 | ||
| [Peer] | [Peer] | ||
| Line 54: | Line 67: | ||
| 6. Once Dan or David give you your private IP, replace ''X.X.X.X'' in ''client.conf'' with it. | 6. Once Dan or David give you your private IP, replace ''X.X.X.X'' in ''client.conf'' with it. | ||
| - | === TODO: Linux CLI instructions === | + | 7. Bring up the interface |
| - | 7. On Mac OS, open the Wireguard GUI. Press Command+O and open ''~/.wireguard/client.conf'' | + | **On Mac OS**, open the Wireguard GUI. Press Command+O and open ''~/.wireguard/client.conf''. Click **Activate** |
| - | 8. Click **Activate** | + | Success looks like\\ |
| - | + | ||
| - | Success looks like | + | |
| {{::screenshot_2025-12-03_at_9.08.01_am.png?400|}} | {{::screenshot_2025-12-03_at_9.08.01_am.png?400|}} | ||
| + | |||
| + | |||
| + | **On Ubuntu**,\\ | ||
| + | <code> | ||
| + | sudo mkdir -p /etc/wireguard | ||
| + | sudo mv ~/.wireguard/client.conf /etc/wireguard/wg0.conf | ||
| + | sudo chmod 600 /etc/wireguard/wg0.conf | ||
| + | sudo wg-quick up wg0 | ||
| + | </code> | ||
| + | |||
| + | use wg show to show status. | ||
| + | ==== Windows ==== | ||
| + | 1. Install Windows client from https://www.wireguard.com/install/ | ||
| + | |||
| + | 2. In the wireguard app, select "Add tunnel/Add empty tunnel". A public and private key will be automatically generated for you. Note them. KEEP THE PRIVATE KEY SECRET. | ||
| + | |||
| + | 3. send in your public key to David/Dan | ||
| + | |||
| + | 4. get an IP address in return | ||
| + | |||
| + | 5. add the configuration to the wireguard app. The first two lines | ||
| + | ([Interface] and PrivateKey = <your private key>) will already be present. | ||
| + | Be very careful to not change anything besides your Address. In | ||
| + | particular, do not edit [Peer] PublicKey; that is the server's public key | ||
| + | and does not change. | ||
| + | |||
| + | <code> | ||
| + | [Interface] | ||
| + | PrivateKey = <your private key> | ||
| + | Address = <address from communication with David/Dan>/32 | ||
| + | DNS = 10.20.192.11, front.sepia.ceph.com, ipmi.sepia.ceph.com | ||
| + | MTU = 1200 | ||
| + | |||
| + | [Peer] | ||
| + | PublicKey = kyEHy3ZBewI5RiK4/a0/UQn6O1kMt3h8V3u0OwsfUXc= | ||
| + | AllowedIPs = 172.16.48.0/24, 10.20.192.0/20, 10.20.208.0/20, 172.16.50.0/23, 172.16.53.0/25, 172.16.55.0/26, 172.16.56.0/23, 172.16.59.0/25, 172.16.60.0/25 | ||
| + | Endpoint = 192.86.31.5:1194 | ||
| + | PersistentKeepalive = 25 | ||
| + | </code> | ||
| + | |||
| + | 6. Save the configuration, which should activate the wg0 tunnel. If all goes well, you will see "Latest Handshake" in the Peer section be a few seconds out of date | ||
| + | |||
| + | 7. despite DNS = , the current wireguard client does not properly handle split-horizon DNS. You must add Powershell scripts to the configuration, and enable their execution with a Windows Registry setting. | ||
| + | |||
| + | Add the following after MTU = in the [Interface] section: | ||
| + | |||
| + | <code> | ||
| + | PostUp = powershell -ExecutionPolicy Bypass -File "C:\Wireguard\wg-up.ps1" | ||
| + | PostDown = powershell -ExecutionPolicy Bypass -File "C:\Wireguard\wg-down.ps1" | ||
| + | </code> | ||
| + | |||
| + | and add the scripts to C:\Wireguard: | ||
| + | <code> | ||
| + | # wg-up.ps1 | ||
| + | param( | ||
| + | [string[]]$Domains = @("sepia.ceph.com", "front.sepia.ceph.com"), | ||
| + | [string]$DNSServer = "10.20.192.11" | ||
| + | ) | ||
| + | |||
| + | # Ensure admin | ||
| + | if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { | ||
| + | Write-Error "This script must be run as Administrator." | ||
| + | exit 1 | ||
| + | } | ||
| + | |||
| + | # Auto-detect WireGuard interface (by type) | ||
| + | $Interface = Get-NetAdapter | Where-Object { $_.InterfaceDescription -match "WireGuard" -and $_.Status -eq "Up" } | Select-Object -First 1 | ||
| + | |||
| + | if (-not $Interface) { | ||
| + | Write-Error "No active WireGuard interface found." | ||
| + | exit 1 | ||
| + | } | ||
| + | |||
| + | $InterfaceAlias = $Interface.Name | ||
| + | Write-Output "Using WireGuard interface: $InterfaceAlias" | ||
| + | |||
| + | # Add NRPT rules (idempotent) | ||
| + | foreach ($domain in $Domains) { | ||
| + | if (-not (Get-DnsClientNrptRule | Where-Object { $_.Namespace -eq $domain })) { | ||
| + | Write-Output "Adding NRPT rule for $domain -> $DNSServer" | ||
| + | Add-DnsClientNrptRule -Namespace $domain -NameServers $DNSServer | ||
| + | } | ||
| + | } | ||
| + | |||
| + | # Set connection-specific DNS suffix (short names) | ||
| + | Set-DnsClient -InterfaceAlias $InterfaceAlias -ConnectionSpecificSuffix $Domains[0] | ||
| + | Write-Output "Set connection-specific suffix: $($Domains[0]) | ||
| + | </code> | ||
| + | |||
| + | <code> | ||
| + | # wg-down.ps1 | ||
| + | param( | ||
| + | [string[]]$Domains = @("sepia.ceph.com") | ||
| + | ) | ||
| + | |||
| + | # Ensure admin | ||
| + | if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { | ||
| + | Write-Error "This script must be run as Administrator." | ||
| + | exit 1 | ||
| + | } | ||
| + | |||
| + | # Auto-detect WireGuard interface (by type) | ||
| + | $Interface = Get-NetAdapter | Where-Object { $_.InterfaceDescription -match "WireGuard" -and $_.Status -eq "Up" } | Select-Object -First 1 | ||
| + | |||
| + | if (-not $Interface) { | ||
| + | Write-Output "No active WireGuard interface found; skipping cleanup." | ||
| + | exit 0 | ||
| + | } | ||
| + | |||
| + | $InterfaceAlias = $Interface.Name | ||
| + | Write-Output "Using WireGuard interface: $InterfaceAlias" | ||
| + | |||
| + | # Remove NRPT rules safely | ||
| + | foreach ($domain in $Domains) { | ||
| + | Get-DnsClientNrptRule | | ||
| + | Where-Object { $_.Namespace -eq $domain } | | ||
| + | Remove-DnsClientNrptRule -ErrorAction SilentlyContinue | ||
| + | Write-Output "Removed NRPT rule for $domain" | ||
| + | } | ||
| + | |||
| + | # Clear connection-specific suffix | ||
| + | Set-DnsClient -InterfaceAlias $InterfaceAlias -ConnectionSpecificSuffix '' | ||
| + | Write-Output "Cleared connection-specific suffix" | ||
| + | </code> | ||
| + | |||
| + | Add to the registry: | ||
| + | |||
| + | <code> | ||
| + | HKEY_LOCAL_MACHINE\Software\WireGuard\DangerousScriptExecution | ||
| + | </code> | ||
| + | |||
| + | set it to 1. You can do this with a Command prompt running as administrator: | ||
| + | |||
| + | <code> | ||
| + | reg add HKLM\Software\WireGuard /v DangerousScriptExecution /t REG_DWORD /d 1 /f | ||
| + | </code> | ||
| + | |||
| + | |||
| + | ===== More about DNS Configuration on Linux ===== | ||
| + | |||
| + | If you're using systemd-resolved, stop. It is incapable of handling split DNS. I would not use resolvconf. | ||
| + | |||
| + | The way I (dmick) chose on Fedora 41 was to disable systemd-resolved and set up a dnsmasq instance behind /etc/resolv.conf. Here's what I did: | ||
| + | |||
| + | 1) sudo systemctl stop systemd-resolved; sudo systemctl disable systemd-resolved | ||
| + | 2) add this to /etc/systemd/networkd.conf and restart networkd (because I'm running networkd to configure networks): | ||
| + | |||
| + | <code> | ||
| + | [Network] | ||
| + | DynamicUser=no | ||
| + | ManageResolver=false | ||
| + | </code> | ||
| + | |||
| + | 3) install dnsmasq if necessary, and configure it. I chose to put my configuration in /etc/dnsmasq.d/dnsmasq.conf (because my system runs dnsmasq with a conf search path of /etc/dnsmasq.d): | ||
| + | |||
| + | <code> | ||
| + | # add domain to shortnames in /etc/hosts; may be helpful | ||
| + | expand-hosts | ||
| + | # don't use /etc/resolv.conf for servers configured here | ||
| + | no-resolv | ||
| + | |||
| + | # for debugging, enable log-queries | ||
| + | # log-queries | ||
| + | |||
| + | # set the server that should handle these three domains | ||
| + | server=/sepia.ceph.com/10.20.192.11 | ||
| + | server=/front.sepia.ceph.com/10.20.192.11 | ||
| + | server=/ipmi.sepia.ceph.com/10.20.192.11 | ||
| + | |||
| + | # set the upstream servers for anything else | ||
| + | server=1.1.1.1 | ||
| + | server=9.9.9.9 | ||
| + | </code> | ||
| + | | ||
| + | 4) remove the existing /etc/resolv.conf and replace with this: | ||
| + | |||
| + | <code> | ||
| + | nameserver 127.0.0.1 | ||
| + | search front.sepia.ceph.com ipmi.sepia.ceph.com sepia.ceph.com | ||
| + | options ndots:2 | ||
| + | </code> | ||
| + | |||
| + | 5) systemctl restart dnsmasq | ||
| + | |||
| + | Now lookups of shortname or shortname.front or shortname.ipmi should work. Note that dig does not respect the search domains in /etc/resolv.conf by default; you must use dig +search <domain> | ||
| + | |||
| + | |||