Skip to content

Instantly share code, notes, and snippets.

@hucsmn
Last active March 6, 2020 10:44
Show Gist options
  • Save hucsmn/aeac5c51c241815f21f61c24be1f1f7e to your computer and use it in GitHub Desktop.
Save hucsmn/aeac5c51c241815f21f61c24be1f1f7e to your computer and use it in GitHub Desktop.
A record of my installation steps of Arch Linux on a KVM-based VPS server via Live CD.

Arch Linux server installation notes

This article is a record of my own installation steps of Arch Linux on a KVM-based VPS server via Live CD.

The VPS was finally configured to a web server + proxy server + testing machine for development.

Presumptions:

  • x86_64, KVM-based VPS
  • VPS provider allows customed ISO
  • a domain name
  • public IP address (not NAT)

Many of the steps were learned from the Arch Linux wiki.

System installation

Prepare partition

# make a single partition here (mbr table), instructions:
#   `o` create dos mbr table,
#   `n` create new partition,
#   `w` write mbr,
#   `q` quit,
[root@arch /]# fdisk /dev/sda

[root@arch /]# mkfs.ext4 /dev/sda1
[root@arch /]# mount /dev/sda1 /mnt

Install packages

Select fastest mirrors.

[root@arch /]# cp /etc/pacman.d/mirrorlist{,.old}
[root@arch /]# rankmirrors -n 3 /etc/pacman.d/mirrorlist.old > /etc/pacman.d/mirrorlist

Install all the packages (core packages, basic tools, ergonomic tools, administrator utils, http server programs, proxy softwares, and development tools).

[root@arch /]# pacstrap /mnt \
               base linux linux-firmware grub sudo \
               dhcpcd dhclient systemd-resolvconf curl wget aria2 \
               nano vim bash-completion fish man-db pacman-contrib pkgfile \
               openssh mosh tmux ntp net-tools bind-tools gnu-netcat iftop \
               nginx nginx-mod-brotli nginx-mod-naxsi fail2ban acme.sh \
               v2ray trojan wireguard-arch wireguard-tools \
               base-devel cmake git docker go rust npm

If you need a non-volatile kernel, try linux-lts instead of linux (also replace wireguard-arch with wireguard-lts).

Basic configuration

[root@arch /]# genfstab -U /mnt >> /mnt/etc/fstab
[root@arch /]# arch-chroot /mnt

[root@arch /]# echo 'LANG=en_US.UTF-8' > /etc/locale.conf
[root@arch /]# nano /etc/locale.gen    #toggle: en_US.UTF-8 UTF-8 
[root@arch /]# locale-gen

[root@arch /]# ln -sf /usr/share/zoneinfo/REGION/CITY /etc/localtime
[root@arch /]# hwclock --systohc

[root@arch /]# echo 'HOST' > /etc/hostname
[root@arch /]# cat >> /etc/hosts <<'EOF'
               127.0.0.1 localhost
               ::1       localhost
               127.0.0.1 DOMAIN.com HOST
               EOF

Add a new non-privileged user

[root@arch /]# passwd

[root@arch /]# useradd USER
[root@arch /]# passwd USER

[root@arch /]# mkdir -p ~USER
[root@arch /]# chown USER:USER ~USER
[root@arch /]# chmod 0755 ~USER

[root@arch /]# nano /etc/sudoers    #toggle: %wheel ALL=(ALL) ALL
[root@arch /]# gpasswd -a USER wheel

Install bootloader and reboot

[root@arch /]# grub-install --target=i386-pc /dev/sda
[root@arch /]# grub-mkconfig -o /boot/grub/grub.cfg
[root@arch /]# reboot

Server configuration

Reboot to the new system (eject Live CD if necessary) and login as root. Then configure Arch Linux server.

Ethernet interfaces

Assuming that your VPS provider uses DHCP.

To configure DHCP for all the existing ethernet interfaces, edit /etc/systemd/network/20-wired.network.

[Match]
Name = en*

[Network]
DHCP = yes

Make systemd-networkd works.

[root@HOST ~]# systemctl enable systemd-networkd.service
[root@HOST ~]# systemctl start systemd-networkd.service

DNS configuration

The preinstalled systemd-resolved provides resolver services for DNS, DNSSEC, DNS over TLS, mDNS and LLMNR.

A simplest /etc/systemd/resolved.conf.

[Resolve]
DNS = 8.8.8.8
FallbackDNS = 8.8.4.4

Make systemd-resolved works in DNS stub file mode.

[root@HOST ~]# ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
[root@HOST ~]# systemctl enable systemd-resolved.service
[root@HOST ~]# systemctl start systemd-resolved.service

Switch to Google BBR and enable IP forawarding

Google's BBR TCP congestion control algorithm could achieve higher bandwidth and lower latency. Since 4.9, BBRv1 is available in kernel.

Create a sysctl configuration for BBR in /etc/sysctl.d/90-bbr.conf.

net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr

Create another configuration to enable IPv4/IPv6 forwarding in /etc/sysctl.d/95-forward.conf. It is required by docker and NAT.

net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1

Reload sysctl.

[root@HOST ~]# sysctl --system

Start NTP

[root@HOST ~]# systemctl enable ntp.service
[root@HOST ~]# systemctl start ntp.service

SSH login

Push your public keys.

[root@HOST ~]# sudo -u USER bash
[USER@HOST root]$ cd ~
[USER@HOST ~]$ mkdir .ssh
[USER@HOST ~]$ nano .ssh/authorized_keys    #insert your public keys
[USER@HOST ~]$ chmod 0700 .ssh
[USER@HOST ~]$ chmod 0600 .ssh/authorized_keys
[USER@HOST ~]$ chown -R USER:USER .ssh
[USER@HOST ~]$ exit

Modify the following lines in /etc/ssh/sshd_config, replace SSHD_PORT with a number in 10000-65535.

Port SSHD_PORT
PasswordAuthentication no
ClientAliveInterval 30
ClientAliveCountMax 60
LogLevel VERBOSE

Enable and start sshd.

[root@HOST ~]# systemctl enable sshd.service
[root@HOST ~]# systemctl start sshd.service

Firewall

Setup iptables

Simply banned TCP/UDP port 1-9999 except 80 and 443 (remember to set a sshd port > 9999 later). This can block various kinds of annoying bots worldwide.

Add rules into /etc/iptables/iptables.rules and /etc/iptables/ip6tables.rules.

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 1:9999 -j DROP
COMMIT

Make iptables/ip6tables works.

[root@HOST ~]# systemctl enable iptables.service
[root@HOST ~]# systemctl start iptables.service

[root@HOST ~]# systemctl enable ip6tables.service
[root@HOST ~]# systemctl start ip6tables.service

Setup fail2ban

fail2ban is a fully functional python script which analyses logs (usually from journald in Arch) and manages firewall rules to block suspicious IP addresses.

  1. Basic settings.

Edit /etc/fail2ban/jail.local.

[DEFAULT]
banaction = iptables
ignoreip = 127.0.0.1/8 ::1
  1. Settings for sshd.

Create /etc/fail2ban/jail.d/sshd.local, replace with your SSHD_PORT.

[sshd]
enabled = true
backend = systemd
filter = sshd
port = SSHD_PORT

maxretry = 5
findtime = 1d

bantime = 2w
bantime.rndtime = 12h
bantime.maxtime = 6mo

Toggle LogLevel VERBOSE in /etc/ssh/sshd_config, then reload sshd if needed.

  1. Enable and start fail2ban.
[root@HOST ~]# systemctl enable fail2ban.service
[root@HOST ~]# systemctl start fail2ban.service

Further configuration

Now you can login as non-privileged user via SSH.

Custom login shell

[USER@HOST ~]$ chsh -s /usr/bin/fish
# relogin to see that shell has been changed to fish

Note that though fish is an convenient interactive shell, but it is incompatible with the bash grammar (e.g. pacman -Qo $(which nc) whould be write as pacman -Qo (which nc) in fish).

Initialize pkgfile

[USER@HOST ~]$ sudo pkgfile -u

It hints which package to install when command not found.

Clean up pacman

Clean up pacman caches and remove unnecessary packages.

[USER@HOST ~]$ yes | sudo pacman -Scc
[USER@HOST ~]$ pacman -Qtdq | sudo pacman -Rsd -

Upgrade system if necessary.

[USER@HOST ~]$ sudo pacman -Syu

Install the AUR helper yay

[USER@HOST ~]$ git clone https://aur.archlinux.org/yay.git
[USER@HOST ~]$ cd yay
[USER@HOST ~]$ makepkg -si
[USER@HOST ~]$ cd ..
[USER@HOST ~]$ rm -rf yay

Setup Nginx and HTTPS

  1. Setup Nginx HTTP server for ACME challenge.

Make a simple configuration that serves ACME chanllenges in /PATH/TO/ACME/CHALLENGE/ROOT and redirect other requests to the https server (not configured yet).

Edit /etc/nginx/modules.conf and /etc/nginx/nginx.conf.

load_module /usr/lib/nginx/modules/ngx_http_brotli_filter_module.so;
load_module /usr/lib/nginx/modules/ngx_http_brotli_static_module.so;
include modules.conf;

error_log /var/log/nginx/error.log;

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;

    default_type  application/octet-stream;
    charset       utf-8;
    gzip          on;
    brotli        on;
    sendfile      on;

    keepalive_timeout 65;

    server {
        server_name  DOMAIN.com www.DOMAIN.com;
        listen       80;

        location ^~ /.well-known/acme-challenge/ {
            root   /PATH/TO/ACME/CHALLENGE/ROOT;
        }

        location / {
            return 301 https://DOMAIN.com$request_uri;
        }
    }
}

Note: The super easy https/http2 server Caddy written in Go might also be a good alternative to Nginx for non-complex situations.

  1. Issue a Let's Encrypt certificate.

Start Nginx service, then issue a cert using acme.sh, a simpler alternative to certbot.

The web root mode of acme.sh seems do not support wildcard in domain name. Try DNS API/manual mode instead if you really need that.

[USER@HOST ~]$ sudo systemctl start nginx.service
[USER@HOST ~]$ acme.sh --issue -w /PATH/TO/ACME/CHALLENGE/ROOT -d DOMAIN.com -d www.DOMAIN.com

Make sure that /PATH/TO/ACME/CHALLENGE/ROOT is absolute path and the current user has write permission to it.

If successed, acme.sh would save certificates and configurations in $HOME/.acme.sh/DOMAIN.com.

  1. Install certificate.

Firstly, add a server into the http block of /etc/nginx/nginx.conf that serves /PATH/TO/WEBSITE.

    server {
        server_name  DOMAIN.com www.DOMAIN.com;
        listen       443 ssl;
 
        ssl_certificate      /PATH/TO/fullchain.pem;
        ssl_certificate_key  /PATH/TO/privkey.pem;
        ssl_protocols        TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_ciphers          ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;

        #ssl_prefer_server_ciphers off;

        access_log /var/log/nginx/https_access.log;

        error_page   404              /404.html;
        error_page   500 502 503 504  /50x.html;
 
        location / {
            root   /PATH/TO/WEBSITE;
            index  index.html;
        }
    }

Then install certificates and restart nginx. Run acme.sh as root to install certificates into destination (e.g. /etc/ssl). Since running as root might result in wrong ownership of files under $HOME/.acme.sh. Work around it using chown.

[USER@HOST ~]$ sudo acme.sh --force --home HOME_DIR/.acme.sh \
               --install-cert -d DOMAIN.com \
               --key-file /PATH/TO/privkey.pem \
               --fullchain-file /PATH/TO/fullchain.pem \
               --reloadcmd 'systemctl restart nginx.service'
[USER@HOST ~]$ sudo chown -R USER:USER HOME_DIR/.acme.sh

All the installation and issuing parameters you passed to acme.sh would finally be recorded under $HOME/.acme.sh. The automatical renew process acme.sh --cron would reuse these parameters implicitly.

  1. Setup certificates renewal.

By default, Arch Linux use systemd timers instead of cron. Therefore, we need to setup automatical renewal by ourselves.

Firstly, create a systemd service in /etc/systemd/system/acme_renew.service for certificates renewal. Change USER and HOME_DIR to your own.

[Unit]
Description = Renew Lets Encrypt certificates using acme.sh
After = network-online.target
Require = nginx.service

[Service]
Type = oneshot
ExecStart = /usr/bin/acme.sh --log --home HOME_DIR/.acme.sh --cron
ExecStartPost = chown -R USER:USER HOME_DIR/.acme.sh

[Install]
WantedBy = multi-user.target

Then create a timer for that service, in /etc/systemd/system/acme_renew.timer. Also, change HOME_DIR to your $HOME.

[Unit]
Description = Daily renewal of Lets Encrypt certificates using acme.sh

[Timer]
OnCalendar = daily
Persistent = true

[Install]
WantedBy = timers.target

Finally, enable and start certificate renewal service along with timer.

[USER@HOST ~]$ sudo systemctl daemon-reload
 
[USER@HOST ~]$ sudo systemctl enable acme_renew.service
[USER@HOST ~]$ sudo systemctl start acme_renew.service

[USER@HOST ~]$ sudo systemctl enable acme_renew.timer
[USER@HOST ~]$ sudo systemctl start acme_renew.timer

The auto renew script acme.sh --cron would update and reinstall certificates every 00:00 AM then restart Nginx if the certificates need update.

Additional Nginx settings

Add robots.txt

Create a simple robots.txt, in /PATH/TO/WEBSITE/robots.txt.

User-agent: *
Allow: /

WebDAV support

Install htpasswd and nginx-mod-dav-ext from AUR.

[USER@HOST ~]$ yay -S nginx-mod-dav-ext apache-tools

Generate /etc/nginx/htpasswd.conf.

[USER@HOST ~]$ sudo htpasswd -c /etc/nginx/htpasswd.conf USER
# htpasswd will prompt you for password

Insert WebDAV settings into the location / block in /etc/nginx/nginx.conf.

            location ^~ /WEBDAV/LOCATION/ {
                alias /PATH/TO/WEBDAV/DIRECTORY/;

                dav_methods PUT DELETE MKCOL COPY MOVE;
                dav_ext_methods PROPFIND OPTIONS;

                auth_basic "Restricted access";
                auth_basic_user_file htpasswd.conf;
                dav_access user:rw group:rw all:r;

                autoindex on;
                create_full_put_path on;
                client_max_body_size 0;
                client_body_temp_path /srv/client-temp;
            }

Where dav_access user:rw group:rw all:r; indicates Nginx use 0664 permissions to create new files.

Change permissions of /PATH/TO/WEBDAV/DIRECTORY/ and reload Nginx.

[USER@HOST ~]$ sudo gpasswd -a USER http
[USER@HOST ~]$ sudo chown -R http:http /PATH/TO/WEBDAV/DIRECTORY/
[USER@HOST ~]$ find /PATH/TO/WEBDAV/DIRECTORY/ -type d | xargs sudo chmod -R 0775
[USER@HOST ~]$ find /PATH/TO/WEBDAV/DIRECTORY/ -type f | xargs sudo chmod -R 0664
[USER@HOST ~]$ sudo systemctl restart nginx.service

Anti XSS/SQL injection

Add the NAXSI module to /etc/nginx/modules.conf.

load_module /usr/lib/nginx/modules/ngx_http_naxsi_module.so;

Insert NAXSI core rules into the http block, edit /etc/nginx/nginx.conf.

    include naxsi_core.rules;

Configure fail2ban for Nginx

  1. Add/modify fail2ban filters for Nginx.
[USER@HOST ~]$ sudo cp /etc/fail2ban/filter.d/{apache,nginx}-badbots.conf

[USER@HOST ~]$ # insert additional rule for blank user/password
[USER@HOST ~]$ echo '            ^ \[error\] \d+#\d+: \*\d+ no user/password was provided for basic authentication, client: <HOST>, server: \S+, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"\s*$' | sudo sed -ie '/^failregex/r /dev/stdin' /etc/fail2ban/filter.d/nginx-http-auth.conf
  1. Configure Nginx request limitation.

Add global request limitation of each IP into http block in /etc/nginx/nginx.conf.

    limit_req_zone $binary_remote_addr zone=each_ip:10m rate=10r/s;

Add limit_req to desired server block or location block in /etc/nginx/nginx.conf.

        limit_req zone=each_ip burst=5;

Reload Nginx.

[USER@HOST ~]$ sudo systemctl restart nginx.service
  1. Configure fail2ban jails for Nginx.

Create /etc/fail2ban/jail.d/nginx.local.

[nginx-http-auth]
enabled = true
filter = nginx-http-auth
backend = polling
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 6
findtime = 1h
bantime = 5d

[nginx-limit-req]
enabled = true
filter = nginx-limit-req
backend = polling
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 10
findtime = 600
bantime = 7200

[nginx-botsearch]
enabled = true
filter = nginx-botsearch
backend = polling
port = http,https
logpath = /var/log/nginx/https_access.log
maxretry = 10
findtime = 1h
bantime = 3d

[nginx-badbots]
enabled = true
filter = nginx-badbots
backend = polling
port = http,https
logpath = /var/log/nginx/https_access.log
maxretry = 1
findtime = 1h
bantime = 3d
  1. Reload fail2ban.
[USER@HOST ~]$ sudo systemctl restart fail2ban.service

Setup V2Ray proxy server

V2Ray is a highly configurable proxy that supports various protocols and transport methods. The following steps are to setup a V2Ray server of shadowsocks protocol over WebSocket + TLS using Nginx (ss+wss://).

Edit /etc/v2ray/config.json firstly.

{
  "inbounds": [
    {
      "port": INTERNAL_PORT,
      "listen":"127.0.0.1",
      "protocol": "shadowsocks",
      "settings": {
        "ota": false,
        "method": "chacha20-poly1305",
        "password": "PASSWORD"
      },
      "streamSettings": {
        "network": "ws",
        "wsSettings": { "path": "/LOCATION/TO/WS" }
      }
    }
  ],
  "outbounds": [ { "protocol": "freedom" } ]
}

Insert following lines into the server block of https in /etc/nginx/nginx.conf. Make sure that there is no limit_req in this location block or in the upper server/location block.

        location = /LOCATION/TO/WS {
            proxy_redirect      off;
            proxy_pass          http://127.0.0.1:INTERNAL_PORT;
            proxy_http_version  1.1;
            proxy_read_timeout  300s;
            proxy_set_header    Host            $http_host;
            proxy_set_header    Upgrade         $http_upgrade;
            proxy_set_header    Connection      "upgrade";
            proxy_set_header    Accept-Encoding "";
            proxy_set_header    X-Real-IP       $remote_addr;
            proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        }

Enable and start proxy server.

[USER@HOST ~]$ sudo systemctl enable v2ray.service
[USER@HOST ~]$ sudo systemctl start v2ray.service
[USER@HOST ~]$ sudo systemctl restart nginx.service

The client side configuration of V2Ray should be something like:

{
  "inbounds": [
    {
      "port": LOCAL_SOCKS5_PORT,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "protocol": "shadowsocks",
      "settings": {
        "servers": [
          {
            "address": "DOMAIN.com",
            "port": 443,
            "ota": false,
            "method": "chacha20-poly1305",
            "password": "PASSWORD"
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "wsSettings": { "path":"/LOCATION/TO/WS" },
        "tlsSettings": { "serverName": "DOMAIN.com" }
      }
    }
  ]
}

Setup Trojan proxy server

Trojan is a simplified standalone socks5-like proxy protocol over TLS, similar to the above V2Ray ss+wss:// way.

If there is no certificate, generate a self-signed SSL certificate (and disable certificate verify in client side).

[USER@HOST ~]$ openssl req -newkey rsa:2048 -nodes -keyout /PATH/TO/key.pem \
               -x509 -days 3650 -out /PATH/TO/cert.pem

Edit /etc/trojan/config.json.

{
    "run_type": "server",
    "local_addr": "0.0.0.0",
    "local_port": TROJAN_PORT,
    "password": [ "PASSWORD" ],
    "log_level": 1,
    "ssl": {
        "cert": "/PATH/TO/cert.pem",
        "key": "/PATH/TO/key.pem",
        "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384",
        "cipher_tls13": "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384",
        "prefer_server_cipher": true,
        "alpn": [ "h2", "http/1.1" ],
        "reuse_session": true,
        "session_ticket": false,
        "session_timeout": 300
    },
    "tcp": {
        "prefer_ipv4": true,
        "no_delay": true,
        "keep_alive": true,
        "reuse_port": false,
        "fast_open": false,
        "fast_open_qlen": 20
    },
    "mysql": { "enabled": false }
}

Enable and start the Trojan server.

[USER@HOST ~]$ sudo systemctl enable trojan.service
[USER@HOST ~]$ sudo systemctl start trojan.service

Mobile clients of Trojan was under development now. They were currently (2020.03) not that stable and convenient.

Setup WireGuard VPN server

WirdGuard is a fast, cross-platform and easy-to-use VPN protocol that could work in Linux kernel to encapsulate IP packets over UDP.

It sends traffic via UDP as many other VPN softwares will do, which might be QoS-ed by some ISPs. Therefore, the network quality and speed might be not as good as ordinary proxies/tunnels like ShadowSocks, V2Ray, Trojan and Gost.

Manually setup

The following steps demostrate how to manually start a wireguard VPN server and how to manually stop it.

  1. Generate server side private key and public key pair.
[USER@HOST ~]$ wg genkey | tee SERVER_PRIVATE_KEY | wg pubkey > SERVER_PUBLIC_KEY
  1. Start wireguard server.
[USER@HOST ~]$ sudo ip link add dev wg0 type wireguard
[USER@HOST ~]$ sudo ip addr add 10.0.0.1/24 dev wg0
[USER@HOST ~]$ sudo wg set wg0 listen-port SERVER_PORT private-key SERVER_PRIVATE_KEY
[USER@HOST ~]$ sudo wg set wg0 peer CLIENT_PUBLIC_KEY persistent-keepalive 180 allowed-ips 0.0.0.0/0,::/0
[USER@HOST ~]$ sudo ip link set wg0 up

The allowed-ips field valued 0.0.0.0/0,::/0 means allow any client IPs. Please change this value to your client IP 10.0.0.xxx.

  1. Turn on NAT (wg0 -> ens1).
[USER@HOST ~]$ sudo iptables -A FORWARD -i wg0 -j ACCEPT
[USER@HOST ~]$ sudo iptables -t nat -A POSTROUTING -o ens1 -j MASQUERADE
  1. Turn off NAT.
[USER@HOST ~]$ sudo iptables -D FORWARD -i wg0 -j ACCEPT
[USER@HOST ~]$ sudo iptables -t nat -D POSTROUTING -o ens1 -j MASQUERADE
  1. Stop wireguard server.
[USER@HOST ~]$ sudo ip link set wg0 down
[USER@HOST ~]$ sudo ip link del dev wg0

The systemd-networkd approach

The wg-quick script included in wireguard-tools package seems to not work properly, maybe because it automatically setup additional rules/routes that would block SSH connection.

Fortunately, systemd-networkd works well with wireguard (without NAT). Following is the configuration.

  1. Configure the WireGuard NIC.

Edit /etc/systemd/network/90-wireguard.netdev.

[NetDev]
Name = wg0
Kind = wireguard
Description = WireGuard VPN Server (without NAT)

[WireGuard]
ListenPort = SERVER_PORT
PrivateKey = SERVER_PRIVATE_KEY

[WireGuardPeer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 180
  1. Configure the WireGuard network.

Edit /etc/systemd/network/90-wireguard.network.

[Match]
Name = wg0

[Network]
Address = 10.0.0.1/32

[Route]
Gateway = 10.0.0.1
Destination = 10.0.0.0/24
  1. Turn on the WireGuard network.
[USER@HOST ~]$ sudo networkctl reload
  1. Manually turn on/off NAT then.

Same as above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment