1. Requirements
- FreeBSD 9.2.1.6+
- Permanent storage (preferably a ZFS volume)
- DNS domain or a static IP
- Internet access
- Router forwarding of your port of choice
For this example we use IP 10.0.0.0/255.255.255.0 as internal network and IP 10.8.0.0/255.255.255.0 as VPN network.
2. References
- Open VPN
- Open VPN HOWTO
- How to install OpenVPN inside a jail in FreeBSD 9.2.1.6 with access to remote hosts via NAT
3. Create OpenVPN jail and install OpenVPN server
Create a new jail (e.g. name vpn) and add storage to the jail so we can keep our keys in a secure place. I'll mount my storage in '/mnt/openvpn' inside the jail.
SSH to your FreeBSD, enter the jail (jexec vpn tcsh) and install OpenVPN package using pkg manager.
pkg install bash openvpn
pkg autoremove
- Note: The first time it will have to upgrade repositories, so don't worry if it downloads a lot of data. We need bash because the 'source ./vars' command behaves weirdly using tcsh. If you run into a "shared object not found" problem, run 'pkg upgrade' again so it repairs the missing packages or resolve dependencies.
4. Create certificates
Scripts are located at '/usr/local/share/easy-rsa/keys'. I recommend to copy whole directory to mounted storage '/mnt/openvpn'. We have to edit the source file './vars' and update KEY_DIR variable.
- Edit variable KEY_DIR e.g. export KEY_DIR="/mnt/openvpn/keys". New created certificates will be stored in this directory.
- You can also re-define other KEY_ variables for default values which will be used during creation of certificates.
Create new certificate authority key 'ca.key'. It is used to confirm the veracity of the data newly created certificates.
cd /mnt/openvpn/easy-rsa
source ./vars
./clean-all
./build-ca
Create new server key 'server.key'. It will identify your OpenVPN server.
Create Diffie-Hellman parameter.
You can generate your own Diffie-Hellman parameter with command (substitute 2048 for 1024 if you are using 2048 bit keys).
5. OpenVPN server configuration
You can use server template configuration file provided by OpenVPN package (located at /usr/local/share/examples/openvpn/sample-config-files) or create a new server configuration file e.g. '/mnt/openvpn/openvpn.conf'. Than you should edit (or insert) next configuration parameter.
proto udp
dev tun
ca /mnt/openvpn/keys/ca.crt
cert /mnt/openvpn/keys/server.crt
key /mnt/openvpn/keys/server.key
dh /mnt/openvpn/keys/dh1024.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 10.0.0.0 255.255.255.0”
#tls-auth /mnt/openvpn/keys/auth.key 0
#crl-verify /mnt/openvpn/keys/crl.pem
keepalive 10 120
group nobody
user nobody
comp-lzo
persist-key
persist-tun
mssfix
client-config-dir /mnt/openvpn/ccd
status logs/openvpn.status.log
log-append logs/openvpn.log
verb 3
- Replace /mnt/openvpn with the path of your permanent storage.
- The port in which the OpenVPN service listens to is UDP 1194. (For security reasons you can map your router WAN (internet) port e.g. 443 to OpenVPN Jail's port 1194.)
- The file ipp.txt will store the connections so you can get the same IP the last time you connected.
- Parameter client-config-dir can contains additional client configuration parameters for specific user name. It can be used e.g. to route all communication for the specific client through your VPN server.
- certificates can be inserted to the server configuration file (to the client configuration too) directly by this parameters:
-
<ca>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN RSA PRIVATE KEY-----
-----END RSA PRIVATE KEY-----
</key>
key-direction 1
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
-----END OpenVPN Static key V1-----
</tls-auth>
- The key-direction 0/1 value in configuration files is arbitrary and must be the opposite between peers (or omitted entirely).
- If there is no second parameter to tls-auth, you must add this parameter to the profile 'key-direction bidirectional'
6. OpenVPN client configuration
For each client that was configured, we need to generate their own certificate keys '<user name>.key' and '<user name>.crt'.
source ./vars
./build-key <user name>
Again, you can use template configuration file (located at /usr/local/share/examples/openvpn/sample-config-files) or create a new client configuration file. Than you should edit (or insert) next configuration parameter.
dev tun
proto udp
remote my-domain-name.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert <user name>.crt
key <user name>.key
#tls-auth auth.key 1
ns-cert-type server
comp-lzo
mssfix
verb 3
- Replace my-domain-name.com with your DNS domain or with your static ip where VPN server is running.
- If your router is configured to another port mapping, replace 1194 with your custom UDP port.
- This client configuration allow access to your internal network only. If you want to route all your traffic as a true VPN, you have to insert this lines into your client configuration file or create new file <user name> in the directory configured by variable client-config-dir in server configuration file:
push "redirect-gateway def1 local bypass-dhcp"
push "dhcp-option DNS 217.31.204.130"
push "dhcp-option DNS 193.29.206.206"
7. NAT Configuration
As client has access only to internal network you have to enable NAT to allow route traffic from VPN clients through the VPN server. First of all we have to identify which interface is used inside the jail. This command lists all of OpenVPN jail's interfaces name. This could be epair1b, epair2b, epair3b, etc., depends on how many jails you have installed in your FreeBSD install.
For automatic settings of filtering rules create NAT configuration script '/usr/local/etc/ipfw.rules' with this rules.
parameter="$1"
eth=`/sbin/ifconfig | grep "epair" | awk -F':' '{print $1}'`
if ["$parameter" = "stop" ]; then
ipfw -q -f flush
else
ipfw -q -f flush
ipfw -q nat 1 config if $eth
ipfw -q add nat 1 all from 10.8.0.0/24 to any out via $eth
ipfw -q add nat 1 all from any to any in via $eth
fi
8. Final configuration step
Finally, let's edit '/etc/rc.conf' so our configuration can be properly read and set during start of the jail. This enables the OpenVPN service, where to find the configuration for the service, enable NAT and which NAT configuration script shoould be used. Execute below commands to modify '/etc/rc.conf'.
echo 'openvpn_if="tun"' >> /etc/rc.conf
echo 'openvpn_configfile="/mnt/openvpn/openvpn.conf"' >> /etc/rc.conf
echo 'openvpn_dir="/mnt/openvpn"' >> /etc/rc.conf
echo 'cloned_interfaces="tun"' >> /etc/rc.conf
echo 'gateway_enable="YES"' >> /etc/rc.conf
echo 'firewall_enable="YES"' >> /etc/rc.conf
echo 'firewall_script="/usr/local/etc/ipfw.rules"' >> /etc/rc.conf
- Replace /mnt/openvpn/ for the path where you mounted your permanent storage.
9. Check OpenVPN NAT configuration
Now restart the jail and use jexec to get inside the jail again. Lets confirm the firewall is configured properly.
00200 nat 1 ip from any to any in via epair1b
65535 allow ip from any to any
- If you see this output, then the jail correctly executed ipfw.rules script. When rules 0100 and 0200 are not shown, there is something wrong in the configuration file '/etc/rc.conf' or 'ipfw.rules' script.
10. Security Hardening
This section is completely optional. There's an option called tls-auth that checks for a signature in each packet so unsigned ones can be dropped much easily. It helps to obfuscate your OpenVPN service and protects against DoS and unauthorized intruders by creating a static pre-shared hash-based message authentication code (HMAC) key.
What this means is that if the someone doesn't provide this key first, the OpenVPN server won't even entertain the idea of authenticating any request from it.
This key is generated in the server and must be included in each client along with the other files (ca.crt, <user name>.crt and <user name>.key). To create this key type:
Then just uncomment the #tls-auth auth.key line (just remove the #) in the server and client configuration files and you're good to go.
11. Client certificate revocation
If someone looses his keys or you want to disallow someone to connecting to your OpenVPN server, you can configure your server to check list of allowed keys before letting anyone in. And if someone is included, it will deny the access.
To have a revocation list, it must contain at least one user. To revoke user's certificate is easy, just execute commands below. They create a file called crl.pem and this is your revocation list.
source ./vars
./revoke-full <user name>
DataBase Updated
Using configuration from /usr/local/share/easy-rsa/openssl-0.9.8.cnf
<user name>.crt: /C=US/ST=CA/L=Temporal/O=Temporal/OU=Temporal/CN=Temporal/name=Temporal/emailAddress=mail@host.domain
error 23 at 0 depth lookup:certificate revoked
- Note the last line. OpenSSL tried to do a lookup for that user and it failed. This means that the certificate was revoked successfully.
Finally, just uncomment the #crl-verify line in the server configuration and restart your OpenVPN server. The revoked client should fail to connect.
12. Logrotate
Add the following entry in '/etc/newsyslog.conf' for rotating openvpn.log file at the first day of every month at midnight. See 'man 5 newsyslog.conf' for more informations. Newsyslog is already being called once per hour by cron.
Comments