easy-rsa
sudo apt install easy-rsa sudo cp /usr/share/easy-rsa /usr/local/ cd /usr/local/easy-rsa/ sudo cp vars.example vars sudo editor vars
Edit in vars:
set_var EASYRSA_KEY_SIZE 4096 set_var EASYRSA_CERT_EXPIRE <<time in days>> set_var EASYRSA_CERT_RENEW <<time in days>>
cd .. chown <<user>> easy-rsa ./easy-rsa init-pki ./easyrsa build-ca
Password needed for new certs. Store well. Of course you can always install a new ca.crt on the openVPN server and sign all client certificates again.
In this example, all keys and signing requests are doene on the same system and then distributed to all servers and clients. Can only be done this way, if you have physical access to all systems and can use an usb-stick or similar to load keys on all machines.
./easyrsa build-server-full <keyname> nopass ./easyrsa build-client-full <keyname> ./easyrsa gen-dh
The last command will take quite a while. The build-client-full above generates client keys with password protection. If your client is unable to store that password (for example in the machines password storage), you may want to use the nopass option for client keys as well.
Certificates will be in ./pki/issued/
Private Keys will be in ./pki/private/
Each client will need the ca.crt, its own crt and its own key file.
The server will need the ca.crt, its own crt and key file and the dh.pem
TLS-auth
(Text from community.openvpn.net/openvpn/wiki/Hardening) The --tls-auth
option uses a static pre-shared key (PSK) that must be generated in advance and shared among all peers. Generate a PSK with:
openvpn --genkey --secret ta.key
And reference it in the configs as such. The 0/1 value is arbitrary and must be the opposite between peers (or omitted entirely.)
# server-example --tls-auth ta.key 0 # client-example --tls-auth ta.key 1
Bridge-setup
This is a bridge setup with tap device. Like this, clients will get an IP in the same range as other clients on the lan the server’s in. Works better with bonjour/zeroconf/mDNS clients on the network. Basically, the client will not see any difference whether it is connected over VPN or in the LAN.
Make sure that the local DHCP server’s IP address range and the VPN server’s IP address range don’t overlap.
The following config goes to openVPN’s config file. On debian this will be something like /etc/openvpn/server.conf. Start the server with systemctl start openvpn@<<config file name prefix>>. If the config is name server.conf, this will become systemctl start openvpn@server
# Sample OpenVPN 2.0 config file with tap interface needed for .local-domain names to work on vpn only non-default options are included of a many-clients <-> one-server # Comments are preceded with '#' or ';' # port <<port vpn should be on>> proto udp dev tap0 server-bridge <<SERVER IP must be fix>> 255.255.255.0 <<START ADDRESS SSERVER DHCP POOL>> <<END ADDRESS SERVER DHCP POOL>> ca <<location ca.crt>> cert <<location server crt>> key <<location server key>> # This file should be kept secret dh .<<location diffie-hellman pem>> tls-auth <<location tls-auth-key>> 0 # This file is secret ifconfig-pool-persist ipp.txt keepalive 10 120 compress lzo user <<vpn user>> group <<vpn group>> persist-key persist-tun status openvpn-status.log verb 3
Network interfaces for bridging need to be set up in /etc/network/interfaces. The setup below is for a system with one ethernet card. Don’t use the start bridging or stop bridging scripts mentioned in many openvpn manuals.
# The loopback network interface auto lo iface lo inet loopback # The primary network interface will be bridged # and so set to manually iface eth0 inet manual iface tap0 inet manual # set bridge, auto brings it up at boot auto br0 iface br0 inet dhcp bridge_ports eth0 tap0 bridge_hw aa:38:d4:8b:12:5a # set a mac address for the bridge. # Needed to give the server a fixed IP # from a DHCP server in the network
Firewall setup
Use nftables on recent Debian. You don’t want all crap from your VPN going right into your LAN. So you should set up the firewall to only let packages pass that are needed for services you actually want to provide.
TUN-setup (thanks to Apple)
As Apple announced removal of kernel extensions, the tap setup above will soon cease to work with Tunnelblick. So, a new approach is needed using a tun interface. The idea is to use dnsmasq on the server to provide the hostnames otherwise provided by multicast dns.
openVPN setup
Server config file:
port 443 proto udp dev tun ca ./cadir/ca.crt cert ./cadir/name.crt key ./cadir/name.key # This file should be kept secret dh ./cadir/dh.pem tls-auth ta.key 0 # This file is secret # set server address give clients addresses in the same subnet server 10.8.137.0 255.255.255.0 # use the servers dnsmaq to promote fileserver.local to clients push "dhcp-option DNS <<Server IP as seen by client, in our case 10.8.137.1>>" ifconfig-pool-persist ipp.txt keepalive 10 120 compress lzo user openvpn group openvpn persist-key persist-tun status openvpn-status.log verb 3
For Tunnelblick on Mac client side config also needs:
dhcp-option DNS <<10.8.137.1>>
dnsmasq setup
This is the tricky part, if you want to use your server as fileserver with samba. First we don’t want dnsmasq to forward queries to *.local domains to another domain server, so set local=/local/. We need to not only send replies for A records, but also SOA queries. That’s what the auth-* lines are here for. We also want dnsmasq to only answer to queries from openVPN clients, so we set interface=tun0, etc. if we had more than four clients, more lines would be required with further tun devices.
set /etc/dnsmasq.conf as follows:
domain-needed bogus-priv local=/local/ auth-server=<<mDNSserver/Bonjourserver>>.local,10.8.137.1 auth-zone=local auth-soa=1 interface=tun0 interface=tun1 interface=tun2 interface=tun3 no-hosts addn-hosts=/etc/hosts.dnsmasq
Because of no-hosts, dnsmasq doesn’t read from /etc/hosts. I don’t want to mix in more dnsmasq domains in that file. Instead, we use /etc/hosts.dnsmasq:
10.8.137.1 <<mDNSserver/Bonjourserver>>.local <<mDNSserver/Bonjourserver>>
For debugging, start dnsmasq from command line:
sudo dnsmasq --no-daemon --log-queries