Páginas

jueves, 29 de octubre de 2015

Tráfico protegido con una VPN basada en BSD

Cuando estás en una red insegura, la última cosa que quiere es que alguien registre todo el tráfico. Hacer la mayor parte de su trabajo a través de SSH es probablemente la mejor solución, a veces desea encapsular todo su tráfico en un túnel. OpenSSH puede hacer eso con un poco de trabajo extra, pero OpenVPN es una herramienta hecha para este propósito exacto. OpenVPN funciona en todos los BSD. Vamos a utilizar FreeBSD 9 en este tutorial, pero se puede adaptar las ubicaciones de los archivos y la configuración a otros BSD muy fácilmente. Instalar OpenVPN desde ports o paquetes.

Escenario: Un servidor FreeBSD con dos tarjetas de red:
Wan -em1 (192.168.1.250)
Lan - em0 (192.18.3.1).
Dhcp - activado
Firewall - ipfilter

El ordenador cliente ejecuta openBSD 5.6, pf firewall.

se conecta a la red Lan a través de un Switch. Ahora asignamos la dirección IP y el gateway con los siguientes comandos:


Luego, añadiremos OpenVPN para los elementos de inicio, en el cliente y el servidor:

En el sevidor (FreeBSD)
# echo 'openvpn_enable="YES"' >> /etc/rc.conf
# echo 'openvpn_if="tun"' >> /etc/rc.conf

En el cliente (OpenBSD)
# echo 'openvpn_enable=YES' >> /etc/rc.conf.local
# echo 'openvpn_if=tun' >> /etc/rc.conf.local

Vamos a configurar el registro (log) adecuado:
# ssh carles@192.168.1.254
Password:

# vi /etc/syslog.conf:
Agregue al final de /etc/syslog.conf algo como esto:

!openvpn
*.* /var/log/openvpn.log
!*

Crear el archivo openvpn.log y releer el archivo de configuración:

# touch /var/log/openvpn.log
# /etc/rc.d/syslogd reload
Rotación de registro (log) para que no se quede sin espacio en disco:

# cat << END >> /etc/newsyslog.conf  \
/var/log/openvpn.log  600  30    *    @T00  ZC  \
END

Ahora vamos a crear los certs, conectando via ssh al servidor FreeBSD. El port OpenVPN instala easy-rsa, es una herramienta para generar certificados. Haremos nuestra propia copia de trabajo del directorio easy-rsa en un lugar seguro :

# pkg_add -v openvpn
# cp -r /usr/local/share/easy-rsa /root/easy-rsa
# cd /root/easy-rsa

Editar las variables en el archivo "vars" para establecer los valores predeterminados para los certificados. La mayor parte de lo que se quiere cambiar es en la parte inferior. "KEY_SIZE" y "KEY_CN" son los más utilizados, "KEY_CN" se utiliza como el nombre de host del servidor predeterminado para los certificados. No pueden estar en blanco.

export KEY_SIZE=2048
export KEY_COUNTRY="ES"
export KEY_PROVINCE="CA"
export KEY_CITY="Barcelona"
export KEY_ORG="server-carles-freebsd"
export KEY_EMAIL="me@myhost.mydomain"
export KEY_CN="freebsdsvr.linux.bcn"
export KEY_NAME=changeme
export KEY_OU="bsdalways"

Preparar un entorno de Bourne shell para la creación de certificados:

# sh
# . ./vars
Debe ejecutar clean-all la primera vez antes de crear certificados. Si usted ya tiene algunos, serán eliminados .

# ./clean-all
Generar el CA certificado que se utilizará para firmar los otros. Basta con aceptar los valores predeterminados a menos que usted desee anularlos.

# ./build-ca
Generar el certificado de servidor utilizando un nombre de host NC 'openvpn-server'. Es conveniente utilizar el nombre de host del servidor de la NC, pero no es obligatorio. Una vez más, acepte los valores predeterminados.

# ./build-key-server openvpn-server
Generar DH claves:

# ./build-dh
Generar un certificado de cliente para cada cliente, en este caso 'openvpn-openBSD-client. Es conveniente utilizar el nombre de host del cliente de la NC, se utiliza como un identificador.

# ./build-key openvpn-client
Almacenar permanentemente las claves de servidor en un lugar seguro :

# mkdir -p /usr/local/etc/openvpn/keys
# chmod 700 /usr/local/etc/openvpn/ /usr/local/etc/openvpn/keys
# cp /root/easy-rsa/keys/ca.crt /usr/local/etc/openvpn/keys/
# cp /root/easy-rsa/keys/dh*.pem /usr/local/etc/openvpn/keys/
# cp -p /root/easy-rsa/keys/openvpn-server.crt /usr/local/etc/openvpn/keys/
# cp -p /root/easy-rsa/keys/openvpn-server.key /usr/local/etc/openvpn/keys/
En cada cliente, crear un lugar seguro para el archivo de configuración y las claves:

# mkdir -p /usr/local/etc/openvpn/keys
# chmod 700 /usr/local/etc/openvpn/ /usr/local/etc/openvpn/keys

Advertencia de Permiso denegado:
scp: /usr/local/etc/openvpn/keys/: Permission denied

Voy al cliente para cambiar los permisos "solo" para la copia de claves:
# chmod 777 /usr/local/etc/openvpn/ /usr/local/etc/openvpn/keys

Copiar de forma segura el siguiente certificado de cliente y archivos de clave de openvpn-server, en cada cliente en /usr/local/etc/openvpn/keys:

Desde el servidor teclear los siguientes comandos:
# scp /root/easy-rsa/keys/ca.crt carles@192.168.3.60:/usr/local/etc/openvpn/keys/
# scp /root/easy-rsa/keys/openvpn_openBSD_client.crt carles@192.168.3.60:/usr/local/etc/openvpn/keys/
# scp /root/easy-rsa/keys/openvpn_openBSD_client.key carles@192.168.3.60:/usr/local/etc/openvpn/keys/

No olvide revertir los cambios, en el cliente, después de realizar la copia segura (scp):
# chmod 700 /usr/local/etc/openvpn/ /usr/local/etc/openvpn/keys

Garantizar permisos de seguridad en el archivo clave del cliente :
# chmod 600 /usr/local/etc/openvpn/keys/*.key
Next, we'll edit the server configuration for openvpn.conf:

Archivo de configuracióon del servidor:
# cp /usr/local/share/examples/openvpn/sample-config-files/server.conf \
   /usr/local/etc/openvpn/openvpn.conf
# chmod 600 /usr/local/etc/openvpn/openvpn.conf
# vi /usr/local/etc/openvpn/openvpn.conf
Reemplace:

ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
Por:

ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/openvpn-server.crt
key /usr/local/etc/openvpn/keys/openvpn-server.key
Luego reemplace:

dh dh2048.pem
Por:

dh /usr/local/etc/openvpn/keys/dh2048.pem
Finalmente:

comp-lzo
Por:

comp-lzo no
push "comp-lzo no"
LZO compression fue desactivado debido a posibles chosen-plaintext ataques.

Archivo de configuración del cliente - client.conf:

# mkdir /etc/openvpn
# cp /usr/local/share/examples/openvpn/sample-config-files/client.conf \
  /etc/openvpn/client.conf
# chmod 600 /etc/openvpn/client.conf
# vi /etc/openvpn/client.conf
Remplace:

remote my-server-1 1194
Por:

remote 192.168.3.1 1194
topology subnet
:
Utilice el nombre real de su servidor o IP por '192.168.3.1'. Luego, remplace

ca ca.crt
cert client.crt
key client.key  # Este archivo debe ser mantenido en secreto
Por:

ca /usr/local/etc/openvpn/keys/ca.crt
cert /usr/local/etc/openvpn/keys/openvpn-client.crt
key /usr/local/etc/openvpn/keys/openvpn-client.key
Finalmente:

comp-lzo
Por:

comp-lzo no

Ahora podemos iniciar conexiones.

En el servidor, ejecute:

# service openvpn start
$ hostname
freebsdsvr.linux.bcn
$ ps ax |grep openvpn
1503 ??  Ss     0:00.30 /usr/local/sbin/openvpn --cd /usr/local/etc/openvpn --d
4689  0  R+     0:00.00 grep openvpn

Compruebe ifconfig, debería aparecer una nueva interfaz tun. Haga lo mismo en el cliente
# ifconfig -tun0


Iniciar openvpn en el cliente openBSD:

Es necesario el archivo  /etc/rc.d/openvpn

Este es un script rc normal utilizado por openbsd. Lo encontrará en,
http://www.openbsdsupport.org/openvpn-on-openbsd56.html

#######################################
#!/bin/sh
#
# openvpn rc.d script for OpenBSD - by Chris Pfaff
#
# This script acts like normal rc script if the openvpn_flags in rc.conf.local ar
# But if openvpn_flags are set to special string "-use-etc-hostname-" then script
#  It starts the openvpns configured in /etc/hostname.if (eg in /etc/hostname.tun
#  It will start multiple openvpn - each with its own config defined in /etc/host
#  If script detects that a process is already running - it does not try to start
#  It supports usual parameters like: start, check, stop, restart, reload
#
# -d = debug mode - use to see verbose information about executed commands
#

daemon="/usr/local/sbin/openvpn"

. /etc/rc.d/rc.subr

if [ "$daemon_flags" != "-use-etc-hostname-" ]; then 
    # handle as usual
    rc_cmd $1
else
    #special unusual handling
    #start openvpns defined in /etc/hostname.*

    # Edit if necessary
    # This pattern is being used for scanning /etc/hostname.tun*
    # and for finding running openvpn processes
    # and for searching individual openvpn process - then patter is appended with: [^a-zA-Z]${hnif}([^0-9]|$)
    processpattern='openvpn.*--daemon.*'

    [ -n "${_RC_DEBUG}" ] || _n="-n"
    PGREPFLAG="-f"
    PKILLFLAG="-f"
    [ -z "${_RC_DEBUG}" ] && PKILLFLAG="$PGREPFLAG -q"  # quiet if not debug mode
    [ -z "${_RC_DEBUG}" ] && PGREPFLAG="$PGREPFLAG -q"  # quiet if not debug mode
    [ -n "${_RC_DEBUG}" ] && PGREPFLAG="$PGREPFLAG -l"  # list process name in debug mode
    case "$1" in
    start|check)
        [ "$1" == "start" ] && echo $_n "${INRC:+ }${_name} "
        if [ X"${daemon_flags}" = X"NO" ]; then
            _rc_err "$0: need -f to force $1 since ${_name}_flags=NO"
            exit 1
        fi
        allprocstatus=0
        # search all hostname.tun* files which contain openvpn startup command
        hostnamepattern="/etc/hostname.tun*"
        for hostnamefile in $hostnamepattern; do
            if [ "$hostnamefile" = "$hostnamepattern" ]; then
                [ -n "${_RC_DEBUG}" ] && echo "no files $hostnamepattern"
                [ "$2" == "quiet" ] && exit 1
                _rc_exit failed
            fi
            [ -n "${_RC_DEBUG}" ] && echo
            if grep -v "^[  ]*#" "$hostnamefile" | grep -q "$processpattern" ; then
                [ -n "${_RC_DEBUG}" ] && echo "File $hostnamefile is openvpn file - will be started/checked"
            else
                [ -n "${_RC_DEBUG}" ] && echo "File $hostnamefile is not related to openvpn - skipping"
                continue
            fi
            # extract interface name from filename
            hnif=${hostnamefile##/etc/hostname\.}
            if [ -z "$hnif" ]; then
                [ -n "${_RC_DEBUG}" ] && echo "Cannot get interface name from $hostnamefile"
                hnifstatus=1
                allprocstatus=1
                continue
            fi

            # check if process is already running for this network interface - if yes, do nothing and result is ok 
            hnifprocesspattern="${processpattern}[^a-zA-Z]${hnif}([^0-9]|$)"  # eg server_tun0.conf or client_tun0.conf or -dev tun0
            [ -n "${_RC_DEBUG}" ] && echo "Executing: pgrep ${PGREPFLAG} \"$hnifprocesspattern\""
            pgrep ${PGREPFLAG} "$hnifprocesspattern" && continue

            if [ "$1" == "check" ]; then
                [ -n "${_RC_DEBUG}" ] && echo "Missing openvpn process for ${hnif} - see $hostnamefile"
                hnifstatus=1
            else
                echo -n "$hnif "  # write name of started if
                # if process is not running for this interface - start it
                [ -n "${_RC_DEBUG}" ] && echo "Executing: /bin/sh /etc/netstart $hnif "
                /bin/sh /etc/netstart $hnif; hnifstatus=$?
                [ -n "${_RC_DEBUG}" ] && echo " status: $hnifstatus"  # etc/hostname scripts may return 0 even if error occurred
            fi
            [ $hnifstatus -ne 0 ] && allprocstatus=1
        done
        # if ANY failed then return failure - (simple exit if check in quiet mode)
        [ "$2" == "quiet" -a $allprocstatus -ne 0 ] && exit 1
        [ $allprocstatus -ne 0 ] && _rc_exit failed
        [ "$2" == "quiet" ] && exit 0
        _rc_exit ok
        ;;
    stop)
        echo $_n "${INRC:+ }${_name} "
        [ -n "${_RC_DEBUG}" ] && echo "Executing: pkill ${PKILLFLAG} \"$processpattern\""
        pkill ${PKILLFLAG} "$processpattern"
        countdown=10
        while [ "((countdown--))" -gt 0 ]; do
            pgrep ${PKILLFLAG} "$processpattern" >/dev/null || continue
            sleep 1;
        done;
        [ -n "${_RC_DEBUG}" ] && echo "Executing: $0 ${_RC_DEBUG} ${_RC_FORCE} check quiet"
        $0 ${_RC_DEBUG} ${_RC_FORCE} check quiet && _rc_exit failed
        _rc_exit ok
        ;;
    reload)
        echo $_n "${INRC:+ }${_name} "
        [ -n "${_RC_DEBUG}" ] && echo "WARNING: Reload might crash the process if process is chrooted"
        [ -n "${_RC_DEBUG}" ] && echo "Executing: pkill -HUP ${PKILLFLAG} \"$processpattern\""
        pkill -HUP ${PKILLFLAG} "$processpattern" || _rc_exit failed
        sleep 10;
        [ -n "${_RC_DEBUG}" ] && echo "Executing: $0 ${_RC_DEBUG} ${_RC_FORCE} check quiet"
        [ -n "${_RC_DEBUG}" ] && echo "WARNING: Reload might crash the process if process is chrooted"
        $0 ${_RC_DEBUG} ${_RC_FORCE} check quiet || _rc_exit failed
        _rc_exit ok
        ;;
    restart)
        $0 ${_RC_DEBUG} ${_RC_FORCE} stop &&
            $0 ${_RC_DEBUG} ${_RC_FORCE} start
        ;;
    *)
        _rc_usage
        ;;
    esac
fi
########################################


Hacer el script ejecutable:
# chmod +x /etc/rc.d/openvpn

Este script rc /etc/rc.d/openvpn sólo funciona si openvpn_flags se define en rc.conf.local

Con el fin de tener el guión openvpn rc compatible con archivos /etc/hostname.*

Añadir a /etc/rc.conf.local:
openvpn_flags = "- use-etc-hostname -"

Luego agregamos estas lineas al archivo /etc/hostname.msk0 (NIC Ethernet):
dhcp
up
!/usr/local/sbin/openvpn --config /etc/openvpn/client.conf

Puerta de enlace por defecto - gateway:
# cat /etc/mygate
192.168.3.1

Probar conexión al servidor openvpn:
# openvpn --config /etc/openvpn/client.conf


Iniciar openvpn cliente como demonio:
Añadir al archivo /etc/openvpn/client.conf

# Make the server daemonize after initialization
daemon openvpn


# ps ax | grep openvpn
 7085 ??  Ss      0:00.04 openvpn --config /etc/openvpn/client.conf
 8952 p1  R+      0:00.00 grep openvpn (ksh)
# hostname
openBSD.my.domain

# ifconfig tun0


El cliente debe poder hacer ping 10.8.0.1.
$ hostname
openBSD.my.domain
$ ping -c5 10.8.0.1


$ tail /var/log/openvpn.log


En este punto al iniciar el cliente openBSD conectará automáticamente al servidor openvpn:



# tcpdump -i msk0 -np

-p Don't put the interface into promiscuous mode
-n Don't convert addresses to names


Es posible que desee mover /root/easy-rsa fuera del servidor a un lugar seguro para reducir el riesgo de que un keylogger esté copiando las pulsaciones del teclcado. Es autónomo y todavía se puede utilizar para generar más claves en otros lugares. Si lo desea, puede utilizar la opción 'cipher ' para elegir el cifrado fuerte y 'auth' plus 'tls -auth' para permitir HMAC en los paquetes. Si lo habilita

push "redirect-gateway def1 bypass-dhcp"
en el servidor, los clientes conectados anularán temporalmente la puerta de enlace predeterminada y se fijará una nueva puerta de enlace predeterminada en el servidor VPN a través del túnel. El servidor VPN debe estár configurado como un router (gateway_enable="YES" en rc.conf ) y NAT para enrutar tráfico adecuadamente a la red externa (Internet). Si reinicia el servidor, los clientes se vuelven a conectar una vez pasado el tiempo de espera definido en la configuración del cliente.

Key Files

Una explicación de los archivos relevantes, (howto openvpn)
Filename Needed By Purpose Secret
ca.crt server + all clients Root CA certificate NO
ca.key key signing machine only Root CA key YES
dh{n}.pem server only Diffie Hellman parameters NO
server.crt server only Server Certificate NO
server.key server only Server Key YES
client1.crt client1 only Client1 Certificate NO
client1.key client1 only Client1 Key YES
client2.crt client2 only Client2 Certificate NO
client2.key client2 only Client2 Key YES
client3.crt client3 only Client3 Certificate NO
client3.key client3 only Client3 Key YES

Bibliografía:
Originally written by Adam McDougall
https://openvpn.net/index.php/open-source/documentation/howto.html

http://networkfilter.blogspot.com.es/2015/01/be-your-own-vpn-provider-with-openbsd.html
http://www.bsdnow.tv/tutorials/openvpn
https://wiki.freebsd.org/
http://www.openbsd.org/faq/

Unix es genial!.