Here is a practical guide to setting up an OpenVPN server on Debian 12 Bookworm.
The aim is to turn our Debian server into a VPN gateway, allowing our remote Windows clients to connect to our entire network.
This is generally the solution I prefer as it allows easy access to all the company's internal networks (see the gateway mode section).
root@host:~# apt update && apt install openvpn
root@host:~# sed -i 's/#AUTOSTART="all"/AUTOSTART="all"/' /etc/default/openvpn ; systemctl daemon-reload
root@host:~# cd /etc/openvpn/
root@host:~# /usr/share/easy-rsa/easyrsa clean-all
root@host:~# /usr/share/easy-rsa/easyrsa init-pki
WARNING!!!
You are about to remove the EASYRSA_PKI at: /etc/openvpn/pki
and initialize a fresh PKI here.
Type the word 'yes' to continue, or any other input to abort.
Confirm removal: yes
#Sets the validity period of the EasyRSA certificate authority to 10 years (3650 days).
set_var EASYRSA_CA_EXPIRE 3650
#Sets the validity period of EasyRSA-issued certificates to 10 years (3650 days).
set_var EASYRSA_CERT_EXPIRE 3650
#Sets the key size for the EasyRSA certificate authority to 4096 bits, ensuring high security without excessive processing load.
set_var EASYRSA_KEY_SIZE 4096
#Sets EasyRSA certificate revocation list validity to 10 years.
set_var EASYRSA_CRL_DAYS 3650
root@host:~# /usr/share/easy-rsa/easyrsa build-ca nopass
* Notice:
Using Easy-RSA configuration from: /etc/openvpn/pki/vars
* Notice:
Using SSL: openssl OpenSSL 3.0.8 7 Feb 2023 (Library: OpenSSL 3.0.8 7 Feb 2023)
Using configuration from /etc/openvpn/pki/cca2af5c/temp.3299e061
.........+++++
............................+++++
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:openvpn-host
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/etc/openvpn/pki/ca.crt
root@host:~# /usr/share/easy-rsa/easyrsa build-server-full server nopass
root@host:~# /usr/share/easy-rsa/easyrsa gen-dh
root@host:~# /usr/share/easy-rsa/easyrsa build-client-full client01 nopass
root@host:~# for i in $(seq -w 1 10);do /usr/share/easy-rsa/easyrsa build-client-full client"$i" nopass; done
port 1194
proto udp
dev tun
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/server.crt
key /etc/openvpn/pki/private/server.key # the server.key private key must be kept secret
dh /etc/openvpn/pki/dh.pem
# internal tun0 connection IP
server 10.50.8.0 255.255.255.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
# Compression - must be turned on at both end
comp-lzo
persist-key
persist-tun
# parameters to be adjusted according to your network configuration
push "dhcp-option DNS 192.168.0.200"
push "dhcp-option DOMAIN std.local"
push "route 192.168.0.0 255.255.255.0"
status /var/log/openvpn-status.log
# verbose mode
verb 3
root@host:~# systemctl enable openvpn@server.service
root@host:~# systemctl start openvpn@server.service
Gateway mode allows us to make the 192.168.0.0/24 network accessible from the client side.
A few netfilter rules will allow vpn clients to access the entire network.
root@host:~# ip addr sh
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 01:02:a0:21:fd:54 brd ff:ff:ff:ff:ff:ff
inet OPENVPN_IP brd X.X.X.X scope global wan
valid_lft forever preferred_lft forever
inet6 fe80::ff:fe5d:f333/64 scope link
valid_lft forever preferred_lft forever
3: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 11:a2:a9:21:fd:54 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.254 brd X.X.X.X scope global wan
valid_lft forever preferred_lft forever
inet6 fe80::6a05:caff:fe39:c153/64 scope link
valid_lft forever preferred_lft forever
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 500
link/none
inet 10.50.8.1 peer 10.50.8.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::7ea2:577f:e834:7a20/64 scope link stable-privacy
valid_lft forever preferred_lft forever
root@host:~# nft add table ip NAT
root@host:~# nft add chain ip NAT my_masquerade '{ type nat hook postrouting priority 100; }'
root@host:~# nft add rule NAT my_masquerade ip saddr { 10.50.8.0/24 } oifname enp2s0 masquerade
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0;
}
}
table ip NAT {
chain my_masquerade {
type nat hook postrouting priority 100; policy accept;
ip saddr { 10.50.8.0/24 } oifname "enp2s0" masquerade comment "outgoing NAT"
}
}
root@host:~# systemctl enable nftables.service
net.ipv4.ip_forward=1
root@host:~# sysctl -p /etc/sysctl.conf
Of course, we may find ourselves in a situation where we can't install OpenVPN on our router. In this case, we could for example, install our OpenVPN server as a virtual machine.
We obviously need to create a port forwarder on our wan router to redirect OpenVPN traffic (step 1 on the diagram) to our OpenVPN server (step 2).
And that's it, it won't change much in terms of configuration because we still need to enable gateway mode and create a NAT rule.
In fact, all we need to do is apply exactly the same rules as before and we're done.
client
dev tun
proto udp
remote OPENVPN_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client01.crt
key client01.key
comp-lzo
verb 3
Contact :