Product SiteDocumentation Site

10.2. Red virtual privada

Una red virtual privada (VPN: «Virtual Private Network») es una forma de enlazar dos redes locales diferentes a través de Internet utilizando un túnel; el túnel generalmente está cifrado para confidencialidad. Usualmente se utilizan VPNs para integrar una máquina remota a la red local de una empresa.
Muchas herramientas lo proveen. OpenVPN es una solución eficiente, fácil de desplegar y mantener, basada en SSL/TLS. Otra posibilidad es utilizar IPsec para cifrar el tráfico IP entre dos máquinas; este cifrado es transparente, lo que significa que no necesita modificar las aplicaciones ejecutando en estos equipos para tener en cuenta la VPN. También puede utilizar SSH, además de para sus funcionalidades más convencionales, para proveer una VPN. Finalmente, puede establecer una VPN utilizando el protocolo PPTP de Microsoft. Existen otras soluciones, pero están más allá del alcance de este libro.

10.2.1. OpenVPN

OpenVPN es un pedazo de software dedicado a crear redes privadas virtuales. Su configuración involucra crear interfaces de red virtuales en el servidor VPN y en los clientes; es compatible con interfaces tun (para túneles a nivel de IP) y tap (para túneles a nivel Ethernet). En la práctica, usualmente utilizará interfaces tun excepto cuando los clientes VPN deban intengrarse a la red local del servidor a través de un puente Ethernet.
OpenVPN se basa en OpenSSL para toda la criptografía SSL/TLS y funcionalidades asociadas (confidencialidad, autenticación, integridad, falta de repudio). Puede configurarlo con una llave privada compartida o con un certificado X.509 basado en la infraestructura de llave pública. Se prefiere fuertemente esta última configuración ya que permite más flexibilidad cuando se enfrenta a un número creciente de usuarios itinerantes que acceden a la VPN.

10.2.1.1. Infraestructura de llave pública: easy-rsa

El algoritmo RSA es ampliamente utilizado en criptografía de llave pública. Involucra un «par de llaves», compuestas de una llave privada y una llave pública. Las dos llaves están fuertemente relacionadas entre ellas y sus propiedades matemáticas son tales que un mensaje cifrado con la llave pública sólo puede ser descifrado por alguien que conozca la llave privada, lo que asegura confidencialidad. En la dirección opuesta, un mensaje cifrado con la clave privada puede ser descifrado por cualquiera que conozca la llave pública, lo que permite autenticar el origen del mensaje ya que sólo pudo haber sido generado por alguien con acceso a la llave privada. Cuando se asocie una función de hash digital (MD5, SHA1 o una variante más reciente), esto lleva a un mecanismo de firma que puede aplicarse a cualquier mensaje.
Sin embargo, cualquiera puede crear un par de llaves, almacenar cualquier identidad en ella y pretender ser la identidad que elijan. Una solución involucra el concepto de una autoridad de certificación (CA: «Certification Authority») formalizado por el estándar X.509. Este término se refiere a una entidad que posee un par de llaves confiable conocido como certificado raíz. Sólo se utiliza este certificado para firmar otros certificados (pares de llaves), luego que se siguieron suficientes pasos para revisar la identidad almacenada en el par de llaves. Las aplicaciones que utilizan X.509 luego pueden verificar los certificados que se les presente si conocen los certificados raíz confiables.
OpenVPN sigue esta regla. Dado que los CA públicos sólo expiden certificados a cambio de un pago (importante), también es posible crear una autoridad de certificación privada dentro de la empresa. Para este propósito, OpenVPN provee la herramienta easy-rsa que funciona como infraestructura de certificación X.509. Su implementación es un conjunto de scripts que utilizan el programa openssl; puede encontrar estos scripts bajo /usr/share/doc/openvpn/examples/easy-rsa/2.0/.
Los administradores de Falcot Corp utilizan esta herramienta para crear los certificados necesarios, tanto para los servidores como para los clientes. Esto permite que la configuración de todos los clientes sea similar ya que sólo deberán configurarlos para confiar en certificados que provengan de la CA local de Falcot. Esta CA es el primer certificado a crear; para ello los administradores copian el directorio que contiene easy-rsa a una ubicación más apropiada, preferentemente a una máquina que no está conectada a la red para evitar el riesgo de que se roben la llave privada de la CA.
$ cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 pki-falcot
$ cd pki-falcot
Luego almacenan los parámetros necesarios en el archivo vars, especialmente aquellos cuyos nombres comienzan con KEY_; estas variables luego son integradas en el entorno:
$ vim vars
$ grep KEY_ vars
export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA`
export KEY_DIR="$EASY_RSA/keys"
echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR
export KEY_SIZE=2048
export KEY_EXPIRE=3650
export KEY_COUNTRY="FR"
export KEY_PROVINCE="Loire"
export KEY_CITY="Saint-Étienne"
export KEY_ORG="Falcot Corp"
export KEY_EMAIL="admin@falcot.com"
$ . ./vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /home/rhertzog/pki-falcot/keys
$ ./clean-all
El siguiente paso es crear el par de llaves en sí de la CA (durante este paso se almacenarán las dos partes del par de llaves en keys/ca.crt y keys/ca.key):
$ ./build-ca
Generating a 2048 bit RSA private key
..............................................++++++
.......................++++++
writing new private key to 'ca.key'
-----
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.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [Loire]:
Locality Name (eg, city) [Saint-Étienne]:
Organization Name (eg, company) [Falcot Corp]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [Falcot Corp CA]:
Name []:
Email Address [admin@falcot.com]:
Ahora puede crear el certificado para el servidor VPN, así como también los parámetros Diffie-Hellman necesarios en el servidor para la conexión SSL/TLS. Se identifica el servidor VPN por su nombre DNS vpn.falcot.com; se reutiliza este nombre para los archivos de llaves generados (keys/vpn.falcot.com.crt para el certificado público, keys/vpn.falcot.com.key para la llave privada):
$ ./build-key-server vpn.falcot.com
Generating a 2048 bit RSA private key
...............++++++
...........++++++
writing new private key to 'vpn.falcot.com.key'
-----
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.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [Loire]:
Locality Name (eg, city) [Saint-Étienne]:
Organization Name (eg, company) [Falcot Corp]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [vpn.falcot.com]:
Name []:
Email Address [admin@falcot.com]:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /home/rhertzog/pki-falcot/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'FR'
stateOrProvinceName   :PRINTABLE:'Loire'
localityName          :T61STRING:'Saint-\0xFFFFFFC3\0xFFFFFF89tienne'
organizationName      :PRINTABLE:'Falcot Corp'
commonName            :PRINTABLE:'vpn.falcot.com'
emailAddress          :IA5STRING:'admin@falcot.com'
Certificate is to be certified until Oct  9 13:57:42 2020 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
$ ./build-dh
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
..............+.......+.................................++*++*++*
El siguiente paso crea los certificados para los clientes VPN; necesita un certificado para cada equipo o persona autorizada para utilizar la VPN:
$ ./build-key JoeSmith
Generating a 2048 bit RSA private key
................++++++
.............................++++++
writing new private key to 'JoeSmith.key'
-----
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.
-----
Country Name (2 letter code) [FR]:
State or Province Name (full name) [Loire]:
Locality Name (eg, city) [Saint-Étienne]:
Organization Name (eg, company) [Falcot Corp]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [JoeSmith]:Joe Smith
Name []:
Email Address [admin@falcot.com]:joe@falcot.com
[…]
Ahora que se crearon todos los certificados, necesita copiarlos donde correspondan: la llave pública del certificado raíz (key/ca.crt) será almacenada en todas las máquinas (tanto el servidor como los clientes) como /etc/ssl/certs/Falcot_CA.crt. Sólo instalará el certificado del servidor en el servidor (key/vpn.falcot.com.crt en /etc/ssl/vpn.falcot.com.crt y key/vpn.falcot.com.key en /etc/ssl/private/vpn.falcot.com.key con permisos restringidos para que sólo el administrador pueda leerlo), con los parámetros Diffie-Hellman correspondientes (key/dh2048.pem) instalados en /etc/openvpn/dh2048.pem. Instale los certificados de clientes en el cliente de VPN correspondiente de forma similar.

10.2.1.2. Configuración del servidor OpenVPN

El script de inicialización de OpenVPN intenta, de forma predeterminada, iniciar todas las redes privadas virtuales definidas en /etc/openvpn/*.conf. Configurar un servidor VPN entonces es cuestión de almacenar el archivo de configuración correspondiente en este directorio. Un buen punto de partida es /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz que lleva a un servidor bastante estándar. Por supuesto necesitará adaptar algunos parámetros: ca, cert, key y dh describirán las ubicaciones seleccionadas para cada uno (respectivamente: /etc/ssl/certs/Falcot_CA.crt, /etc/ssl/vpn.falcot.com.crt, /etc/ssl/private/vpn.falcot.com.key y /etc/openvpn/dh2048.pem). La directiva server 10.8.0.0 255.255.255.0 define la subred utilizada por la VPN; el servidor utilizará la primera dirección IP en el rango (10.8.0.1) y se asignarán a los clientes el resto de las direcciones.
Con esta configuración OpenVPN creará una interfaz de red virtual al iniciar, generalmente con el nombre tun0. Sin embargo, normalmente se configuran los firewalls al mismo tiempo que las interfaces de red reales, lo que ocurre antes que inicie OpenVPN. La creación de una interfaz de red virtual persistente, y configurar OpenVPN para que la utilice, es una buena práctica recomendada. Esto además permite elegir el nombre de esta interfaz. A tal efecto, openvpn -mktun -dev vpn -dev-type tun crea una interfaz de red virtual llamada vpn de tipo tun; puede integrar fácilmente esta orden en el script de configuración del firewall o en la directiva up del archivo /etc/network/interfaces. Debe actualizar también el archivo de configuración de OpenVPN de forma acorde, con las directivas dev vpn y dev-type tun.
Sin más cambios, los clientes VPN sólo pueden acceder el servidor VPN en sí a través de la dirección 10.8.0.1. Para permitir a los clientes que accedan la red local (192.168.0.0/24) necesitará agregar una directiva push route 192.168.0.0 255.255.255.0 a la configuración de OpenVPN para que los clientes VPN automáticamente obtengan una ruta de red que les indique que esta red está disponible a través de la VPN. Lo que es más, los equipos en la red local también necesitarán ser informados que la ruta a la VPN es a través del servidor de VPN (esto funciona automáticamente cuando instala el servidor VPN en la puerta de enlace). Otra alternativa es configurar el servidor VPN para realizar enmascaramiento de IPs de forma que las conexiones que provengan de los clientes VPN parezcan provenir del servidor VPN en su lugar (revise la Sección 10.1, “Puerta de enlace”).

10.2.1.3. Configuración del cliente OpenVPN

Para configurar un cliente OpenVPN también necesita crear un archivo de configuración en /etc/openvpn/. Puede conseguir una configuración estándar utilizando /usr/share/doc/openvpn/examples/sample-config-files/client.conf como punto de partida. La directiva remote vpn.falcot.com 1194 describe la dirección y puerto del servidor OpenVPN; también necesita adaptar ca, cert y key para describir la ubicación de los archivos de llave.
Si no se debe iniciar la VPN automáticamente durante el inicio, configure la directiva AUTOSTART como none en el archivo /etc/default/openvpn. Siempre es posible iniciar o detener una conexión VPN dada con /etc/init.d/openvpn start nombre y /etc/init.d/openvpn stop nombre (donde la conexión nombre coincide con aquella definida en /etc/openvpn/nombre.conf).
El paquete network-manager-openvpn-gnome contiene una extensión para Network Manager (revise la Sección 8.2.4, “Configuración de red automática para usuarios errantes”) que permite administrar redes privadas virtuales OpenVPN. Esto permite que cada usuario configure gráficamente sus conexiones OpenVPN y las controle desde el ícono del gestor de red.

10.2.2. Red privada virtual con SSH

En realidad existen dos formas de crear una red privada virtual con SSH. La histórica involucra establecer una capa PPP sobre el enlace SSH. Se describe este método en el siguiente «howto»:
The second method is more recent, and was introduced with OpenSSH 4.3; it is now possible for OpenSSH to create virtual network interfaces (tun*) on both sides of an SSH connection, and these virtual interfaces can be configured exactly as if they were physical interfaces. The tunneling system must first be enabled by setting PermitTunnel to “yes” in the SSH server configuration file (/etc/ssh/sshd_config). When establishing the SSH connection, the creation of a tunnel must be explicitly requested with the -w any:any option (any can be replaced with the desired tun device number). This requires the user to have administrator privilege on both sides, so as to be able to create the network device (in other words, the connection must be established as root).
Ambos métodos para crear redes privadas virtuales sobre SSH son bastante directos. Sin embargo, la VPN que proveen no es la más eficiente disponible; en particular, no maneja muy bien altos niveles de tráfico.
La explicación es que cuando se encapsula TCP/IP en una conexión TCP/IP (para SSH) se utiliza el protocolo TCP dos veces, una vez para la conexión SSH y una vez dentro del túnel. Esto genera problemas, especialmente debido a la forma en la que TCP se adapta a condiciones de red modificando los tiempo de espera. El siguiente sitio describe el problema en más detalle: Por lo tanto debe limitar el uso de VPNs sobre SSH a túneles esporádicos y de un solo uso que no tengan requisitos de rendimiento.

10.2.3. IPsec

IPsec, a pesar de ser el estándar en VPNs IP, es bastante más complejo en su implementación. El motor de IPsec está incorporado al núcleo Linux; el paquete ipsec-tools provee las partes necesarias en espacio de usuario, las herramientas de control y configuración. En términos concretos, el archivo /etc/ipsec-tools.conf de cada equipo contiene los parámetros de los túneles IPsec (en términos de IPsec: asociaciones de seguridad, «Security Associations») en los que el equipo está involucrado; el script /etc/init.d/setkey provee una forma de iniciar y detener el túnel (cada túnel es un enlace seguro a otra máquina conectada a la red privada virtual). Puede construir este archivo a mano desde la documentación que provee la página de manual setkey(8). Sin embargo, escribir los parámetros para todos los equipos en un conjunto de máquinas no trivial se convierte fácilmente en una tarea ardua ya que la cantidad de túneles crece rápidamente. Instalar un demonio IKE (intercambio de llaves IPsec: «IPsec Key Exchange») como racoon, strongswan o openswan hace el proceso mucho más simple centralizando la administración y más seguro rotando las claves periódicamente.
A pesar de su estado como referencia, la complejidad de configuración de IPsec restringe su uso en la práctica. Generalmente se preferirán soluciones basadas en OpenVPN cuando los túneles necesarios no sean muchos ni demasiado dinámicos.

10.2.4. PPTP

PPTP (protocolo de túneles punto a punto: «Point-to-Point Tunneling Protocol») utiliza dos canales de comunicación, uno para datos de control y otro para los datos; este último utiliza el protocolo GRE (encapsulación genérica de enrutamiento: «Generic Routing Encapsulation»). Luego se establece un enlace PPP estándar sobre el canal de intercambio de datos.

10.2.4.1. Configuración del cliente

El paquete pptp-linux contiene un cliente PPTP para Linux fácil de configurar. Las instrucciones a continuación están inspiradas en la documentación oficial:
Los administradores de Falcot crearon varios archivos: /etc/ppp/options.pptp, /etc/ppp/peers/falcot, /etc/ppp/ip-up.d/falcot y /etc/ppp/ip-down.d/falcot.

Ejemplo 10.2. El archivo /etc/ppp/options.pptp

# PPP options used for a PPTP connection
lock
noauth
nobsdcomp
nodeflate

Ejemplo 10.3. El archivo /etc/ppp/peers/falcot

# vpn.falcot.com is the PPTP server
pty "pptp vpn.falcot.com --nolaunchpppd"
# the connection will identify as the "vpn" user
user vpn
remotename pptp
# encryption is needed
require-mppe-128
file /etc/ppp/options.pptp
ipparam falcot

Ejemplo 10.4. El archivo /etc/ppp/ip-up.d/falcot

# Create the route to the Falcot network
if [ "$6" = "falcot" ]; then
  # 192.168.0.0/24 is the (remote) Falcot network
  route add -net 192.168.0.0 netmask 255.255.255.0 dev $1
fi

Ejemplo 10.5. El archivo /etc/ppp/ip-down.d/falcot

# Delete the route to the Falcot network
if [ "$6" = "falcot" ]; then
  # 192.168.0.0/24 is the (remote) Falcot network
  route del -net 192.168.0.0 netmask 255.255.255.0 dev $1
fi

10.2.4.2. Configuración del servidor

pptpd es el servidor PPTP para Linux. Necesitará cambiar pocas cosas de su archivo de configuración principal, /etc/pptpd.conf: localip (dirección IP local) y remoteip (dirección IP remota). En el ejemplo a continuación el servidor PPTP siempre utiliza la dirección 192.168.0.199 y los clientes PPTP reciben una dirección IP desde 192.168.0.200 a 192.168.0.250.

Ejemplo 10.6. El archivo /etc/pptpd.conf

# TAG: speed
#
#       Specifies the speed for the PPP daemon to talk at.
#
speed 115200

# TAG: option
#
#       Specifies the location of the PPP options file.
#       By default PPP looks in '/etc/ppp/options'
#
option /etc/ppp/pptpd-options

# TAG: debug
#
#       Turns on (more) debugging to syslog
#
# debug

# TAG: localip
# TAG: remoteip
#
#       Specifies the local and remote IP address ranges.
#
#       You can specify single IP addresses separated by commas or you can
#       specify ranges, or both. For example:
#
#               192.168.0.234,192.168.0.245-249,192.168.0.254
#
#       IMPORTANT RESTRICTIONS:
#
#       1. No spaces are permitted between commas or within addresses.
#
#       2. If you give more IP addresses than MAX_CONNECTIONS, it will
#          start at the beginning of the list and go until it gets
#          MAX_CONNECTIONS IPs. Others will be ignored.
#
#       3. No shortcuts in ranges! ie. 234-8 does not mean 234 to 238,
#          you must type 234-238 if you mean this.
#
#       4. If you give a single localIP, that's ok - all local IPs will
#          be set to the given one. You MUST still give at least one remote
#          IP for each simultaneous client.
#
#localip 192.168.0.234-238,192.168.0.245
#remoteip 192.168.1.234-238,192.168.1.245
#localip 10.0.1.1
#remoteip 10.0.1.2-100
localip 192.168.0.199
remoteip 192.168.0.200-250
La configuración PPP utilizada por el servidor PPTP también necesita algunos cambios en el archivo /etc/ppp/pptpd-options. Los parámetros importantes son el nombre del servidor (pptp), el nombre del dominio (falcot.com y la dirección IP para los servidores DNS y WINS.

Ejemplo 10.7. El archivo /etc/ppp/pptpd-options

## turn pppd syslog debugging on
#debug

## change 'servername' to whatever you specify as your server name in chap-secrets
name pptp
## change the domainname to your local domain
domain falcot.com

## these are reasonable defaults for WinXXXX clients
## for the security related settings
# The Debian pppd package now supports both MSCHAP and MPPE, so enable them
# here. Please note that the kernel support for MPPE must also be present!
auth
require-chap
require-mschap
require-mschap-v2
require-mppe-128

## Fill in your addresses
ms-dns 192.168.0.1
ms-wins 192.168.0.1

## Fill in your netmask
netmask 255.255.255.0

## some defaults
nodefaultroute
proxyarp
lock
The last step involves registering the vpn user (and the associated password) in the /etc/ppp/chap-secrets file. Contrary to other instances where an asterisk (*) would work, the server name must be filled explicitly here. Furthermore, Windows PPTP clients identify themselves under the DOMAIN\\USER form, instead of only providing a user name. This explains why the file also mentions the FALCOT\\vpn user. It is also possible to specify individual IP addresses for users; an asterisk in this field specifies that dynamic addressing should be used.

Ejemplo 10.8. El archivo /etc/ppp/chap-secrets

# Secrets for authentication using CHAP
# client        server  secret      IP addresses
vpn             pptp    f@Lc3au     *
FALCOT\\vpn     pptp    f@Lc3au     *