Uno de los primeros proyectos que hice con una Raspberry Pi fue crear un servidor VPN para poder acceder a mi red doméstica y navegar tranquilamente desde conexiones públicas. O, para cuando viajo a países como China, en los que el acceso a ciertas páginas está bloqueado, poder navegar tranquilamente.
Tengo una Raspberry Pi 2 permanentemente encendida, con una distribución OpenElec para usar Kodi al ver la televisión. Quería utilizar esta máquina como servidor VPN, pero tras investigar mucho he decidido desistir por los muchos problemas que tiene el emplear una distribución no completa como es OpenElec. Así que mejor lo hago en otra Raspberry exclusiva (una B), con una distribución decente, como es Raspbian.
Hay miles de tutoriales por internet sobre cómo hacer esto. Yo voy a seguir fundamentalmente este en dos partes, que me parece maravilloso (aunque hay varias cosas que han cambiado con las nuevas versiones de OpenVPN y no se puede seguir tal cual):
Building A Raspberry Pi VPN Part One: How And Why To Build A Server
Building A Raspberry Pi VPN Part Two: Creating An Encrypted Client Side
Configuraré mi portátil del trabajo (Windows), mi portátil personal (Mac) y mi iPhone para poder acceder a la VPN.
Pasos previos
Instalo Raspbian, cambio la contraseña, compruebo que puedo acceder a la Raspberry Pi por SSH, desde otro ordenador conectado a la misma red local. Y actualizo todo con sudo apt-get update
y sudo apt-get upgrade
.
También tengo que asegurarme de que la Raspberry Pi tiene asignada una IP estática dentro de la red local, o bien a mano (ver esta entrada) o en mi router. Hecho (no explico cómo hacerlo por el router porque en cada router se hace de una forma, aunque todos son similares). Supongamos que es la 192.168.1.45.
También seguramente necesite un servidor dns dinámico como no-ip.com, para poder acceder desde cualquier sitio al servidor, que seguramente tenga una IP dinámica. Puedo hacerlo siguiendo las instrucción ques expliqué en esta entrada.
Una cosa más en el router: debo hacer que todo paquete que llegue al puerto 1194 UDP sea dirigido a mi Raspberry Pi. Hecho (tampoco lo explico, si tienes dudas, googlea tu modelo de router).
Instalando OpenVPN
Instalo OpenVPN:
sudo apt-get install openvpn easy-rsa
Se me instala la versión 2.3.4.
Voy a generar las claves RSA. Empiezo por darme permiso de supersusuario, para no tener que andar haciendo sudo
todo el rato:
sudo -s
Vamos a emplear easy-rsa
.
Y ahora:
mkdir /etc/openvpn/easy-rsa
cp /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
cd /etc/openvpn/easy-rsa
nano /etc/openvpn/easy-rsa/vars
Busco dentro del fichero /etc/openvpn/easy-rsa/vars
la línea que dice export EASY_RSA="`pwd`"
y lo cambio por:
export EASY_RSA=”/etc/openvpn/easy-rsa”
Y ahora genero los certificados, ejecutando los siguientes comandos:
source ./vars
./clean-all
./build-ca
¡Ojo! Si no es la primera vez que seguimos estos pasos es posible que ya tengamos algunos certificados generados en el directorio /etc/openvpn/easy-rsa
. En este caso, NO debemos ejecutar el comando ./clean-all
Al ejecutar ./build-ca
saltarán una serie de preguntas (Country name, State or Province Name, Locality Name, Organization Name, Organizational Unit Name, Common Name, Name), que yo prefiero no rellenar y dejo los valores por defecto, pulsando Enter.
Ahora definimos el nombre del servidor, en mi caso raspivpn
:
./build-key-server raspivpn
Nuevamente, nos pedirá rellenar una serie de nombres, que dejo en sus valores por defecto, fijándome que el Common Name que me ofrece por defecto y apruebo es el que di al servidor, raspivpn
. El Challenge Pasword lo dejo en blanco, y cuando me pregunte «Sign the certificate? [y/n]», pues diré que sí (y), naturalmente.
Con esto ya tenemos configurado el servidor. Ahora nos queda generar las claves de los clientes y configurarlos.
Creo un certificado para cada usuario:
./build-key-pass usuario1
./build-key-pass usuario2
./build-key-pass usuario3
./build-key-pass usuario4
./build-key-pass usuario5
...
Introduzco la contraseña que quiero tenga cuando dice «Enter PEM pass phrase», y el resto de opciones por defecto.
Y ahora encriptamos las llaves con des3:
openssl rsa -in usuario1.key -des3 -out usuario1.3des.key
openssl rsa -in usuario2.key -des3 -out usuario2.3des.key
openssl rsa -in usuario3.key -des3 -out usuario3.3des.key
openssl rsa -in usuario4.key -des3 -out usuario4.3des.key
openssl rsa -in usuario5.key -des3 -out usuario5.3des.key
E introducimos una nueva contraseña (o la misma).
Volvemos al directorio de easy-rsa:
cd /etc/openvpn/easy-rsa/
Ahora generamos el intercambio de llaves Diffie-Hellman. Esto puede tardar (en mi caso, una hora y cuarto, porque dejé la opción por defecto de encriptación 2048 bit):
./build-dh
Y la protección contra un ataque de DoS, generando una llave HMAC estática:
openvpn --genkey --secret keys/ta.key
Ya está todo instalado y creado. Falta configurar OpenVPN. Para ello vamos a crear un fichero /etc/openvpn/server.conf
con el contenido de este archivo.
nano /etc/openvpn/server.conf
Más adelante he descubierto que OpenVPN no arranca tras reiniciar el servidor. Investigando, he llegado a que hay que comentar la primera línea de este fichero: # local 192.168.1.45
. Entonces, en mi caso, lo dejo así:
#local 192.168.1.45 # SWAP THIS NUMBER WITH YOUR RASPBERRY PI IP ADDRESS
dev tun
proto udp #Some people prefer to use tcp. Don't change it if you don't know.
port 1194
ca /etc/openvpn/easy-rsa/keys/ca.crt
cert /etc/openvpn/easy-rsa/keys/raspivpn.crt # SWAP WITH YOUR CRT NAME
key /etc/openvpn/easy-rsa/keys/raspivpn.key # SWAP WITH YOUR KEY NAME
dh /etc/openvpn/easy-rsa/keys/dh2048.pem # If you changed to 2048, change that here!
server 10.8.0.0 255.255.255.0
# server and remote endpoints
ifconfig 10.8.0.1 10.8.0.2
# Add route to Client routing table for the OpenVPN Server
push "route 10.8.0.1 255.255.255.255"
# Add route to Client routing table for the OpenVPN Subnet
push "route 10.8.0.0 255.255.255.0"
# your local subnet
push "route 192.168.1.45 255.255.255.0" # SWAP THE IP NUMBER WITH YOUR RASPBERRY PI IP ADDRESS
# Set primary domain name server address to the SOHO Router
# If your router does not do DNS, you can use Google DNS 8.8.8.8
push "dhcp-option DNS 192.168.1.1" # This should already match your router address and not need to be changed.
# Override the Client default gateway by using 0.0.0.0/1 and
# 128.0.0.0/1 rather than 0.0.0.0/0. This has the benefit of
# overriding but not wiping out the original default gateway.
push "redirect-gateway def1"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/keys/ta.key 0
cipher AES-128-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn-status.log 20
log /var/log/openvpn.log
verb 1
Otra cosa, tenemos que redirigir el tráfico de internet, ya que Raspbian por defecto no lo hace. Para ello editamos el siguiente fichero:
nano /etc/sysctl.conf
Buscamos la línea donde dice:
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
Y lo descomentamos:
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
Aplicamos los cambios con el siguiente comando:
sysctl -p
Ahora queda desbloquear OpenVPN en el firewall, y además hacer que se haga en cada reinicio, ya que las excepciones del cortafuegos no se quedan grabadas. Para ello creamos este pequeño script:
nano /etc/firewall-openvpn-rules.sh
Y dentro del fichero escribimos lo siguiente:
#!/bin/sh
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j SNAT --to-source 192.168.1.45
Grabamos y salimos. Ahora toca darle permisos de ejecución a este fichero, y cambiarle el usuario a root
:
chmod 700 /etc/firewall-openvpn-rules.sh
chown root /etc/firewall-openvpn-rules.sh
En las versiones anteriores de Raspbian, bastaba con editar el fichero /etc/network/interfaces
:
nano /etc/network/interfaces
buscar la línea:
iface eth0 inet manual
y debajo de ella, con un sangrado, añadir:
pre-up /etc/firewall-openvpn-rules.sh
Pero si se tiene Raspbian Jessie o superior, hay que añadir además «auto eth0» en la línea anterior, de forma que finalmente debe quedar así:
auto eth0
iface eth0 inet manual
pre-up /etc/firewall-openvpn-rules.sh
Con esto ya garantizamos que tras cada reinicio se abre el Firewall para OpenVPN. Así que reiniciamos la Raspberry Pi:
reboot
Configurando el cliente
Ya tenemos el servidor VPN en marcha. Ahora vamos a configurar los clientes.
Pero seguimos todavía en el servidor. Vamos a crear los ficheros de configuración que instalaremos en los clientes.
Creamos un fichero:
nano /etc/openvpn/easy-rsa/keys/Default.txt
Y copiamos lo siguiente:
client
dev tun
proto udp
remote TU-SERVIDOR-AQUI 1194
resolv-retry infinite
nobind
persist-key
persist-tun
mute-replay-warnings
ns-cert-type server
key-direction 1
cipher AES-128-CBC
comp-lzo
verb 1
mute 20
Donde dice TU-SERVIDOR-AQUI
pondremos la dirección pública de nuestro servidor. Puede ser una IP, o un nombre como mi.servidorVPN.com
. Lo más probable es que aquí pongas una dirección de dominio dinámico gratuita como las que ofrece no-ip.com
, que expliqué cómo se hace en otro post.
Ahora para generar los ficheros de configuración de cada cliente descargamos este pequeño script maravilloso aquí, y copiamos su contenido en un fichero en /etc/openvpn/easy-rsa/keys/MakeOVPN.sh
(he corregido dos cosas menores):
#!/bin/bash
# Default Variable Declarations
DEFAULT="Default.txt"
FILEEXT=".ovpn"
CRT=".crt"
KEY=".3des.key"
CA="ca.crt"
TA="ta.key"
#Ask for a Client name
echo "Please enter an existing Client Name:"
read NAME
#1st Verify that client’s Public Key Exists
if [ ! -f $NAME$CRT ]; then
echo "[ERROR]: Client Public Key Certificate not found: $NAME$CRT"
exit
fi
echo "Client’s cert found: $NAME$CR"
#Then, verify that there is a private key for that client
if [ ! -f $NAME$KEY ]; then
echo "[ERROR]: Client 3des Private Key not found: $NAME$KEY"
exit
fi
echo "Client’s Private Key found: $NAME$KEY"
#Confirm the CA public key exists
if [ ! -f $CA ]; then
echo "[ERROR]: CA Public Key not found: $CA"
exit
fi
echo "CA public Key found: $CA"
#Confirm the tls-auth ta key file exists
if [ ! -f $TA ]; then
echo "[ERROR]: tls-auth Key not found: $TA"
exit
fi
echo "tls-auth Private Key found: $TA"
#Ready to make a new .opvn file - Start by populating with the default file
cat $DEFAULT > $NAME$FILEEXT
#Now, append the CA Public Cert
echo "" >> $NAME$FILEEXT
cat $CA >> $NAME$FILEEXT
echo "" >> $NAME$FILEEXT
#Next append the client Public Cert
echo "" >> $NAME$FILEEXT
cat $NAME$CRT | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' >> $NAME$FILEEXT
echo "" >> $NAME$FILEEXT
#Then, append the client Private Key
echo "" >> $NAME$FILEEXT
cat $NAME$KEY >> $NAME$FILEEXT
echo "" >> $NAME$FILEEXT
#Finally, append the TA Private Key
echo "" >> $NAME$FILEEXT
cat $TA >> $NAME$FILEEXT
echo "" >> $NAME$FILEEXT
echo "Done! $NAME$FILEEXT Successfully Created."
#Script written by Eric Jodoin
#No newline at end of file
Damos permiso de ejecución al script:
cd /etc/openvpn/easy-rsa/keys/
chmod 700 MakeOVPN.sh
Y ejecutamos el script:
./MakeOVPN.sh
Nos pide el nombre del cliente. Introduzco usuario1
, trabaja un poco y crea el fichero usuario1.ovpn
. Repito con el resto de usuarios.
De esta forma se me generan unos ficheros usuario1.ovpn
, usuario2.ovpn
, etc. que son los que cargaré a continuación en los clientes.
Basta con cargar el fichero .ovpn, introducir la contraseña, y listo.
Lo he probado de forma exitosa en:
iPhone, con OpenVPN.
Mac, con TunnelBlick
Windows, con OpenVPN Connect
Me consta que OpenVPN Connect también funciona en Android, pero no lo he probado.
Referencias
https://nxfifteen.me.uk/2015/02/07/raspberry-pi-powered-openvpn-server/