OpenVPN, del que sabías tan poco

OpenVPN, cuánto en esta palabra. Un servidor VPN de código abierto multiplataforma, altamente personalizable y gratuito, que en realidad es el estándar de facto para organizar el acceso a las redes corporativas internas. La mayoría de los administradores lo usan con configuraciones predeterminadas o con configuraciones típicas que se describen ampliamente en diferentes INSTRUCCIONES. ¿Pero es OpenVPN tan simple como parece a primera vista? En este artículo, consideraremos los mecanismos internos de OpenVPN, ocultos a los ojos, que cambian drásticamente la idea de sus capacidades.


El servidor OpenVPN se distribuye en forma de código fuente o paquetes compilados listos para instalar para varios sistemas operativos. OpenSSL se utiliza como una biblioteca que proporciona cifrado.


La mayoría de las configuraciones para conectar clientes al servidor, así como entre servidores, implican el uso de un conjunto de claves privadas o privadas / públicas para garantizar la seguridad del tráfico interno. Para las redes corporativas en modo MultiPoint-To-SinglePoint, generalmente se usa su propio centro de certificación PKI, que es fácil de construir utilizando easy-rsa o XCA . Para la comunicación entre servidores punto a punto, se utiliza principalmente una configuración de clave compartida. Recordemos los mecanismos y capacidades básicos y bien conocidos.


Mecanismos y capacidades clave


  • Autenticación de certificado


    Se ha escrito una gran cantidad de documentación al respecto. El punto es simple. Se está creando una autoridad de certificación que emite certificados de usuario. Con la ayuda de una autoridad de certificación, se proporciona un control para conectar a los usuarios al servidor OpenVPN. Cuando el certificado caduca o se revoca, se bloquea el acceso del usuario. Las claves privadas con una contraseña establecida en ellas, emitidas junto con el certificado, proporcionan seguridad contra conexiones no autorizadas a recursos internos.


  • Claves privadas punto a punto


    Desde el punto de vista de conectar solo un usuario / servidor a los recursos de la empresa, se utiliza un esquema con claves privadas. Se genera una clave en uno de los hosts, que se comparte entre el servidor y el cliente.



En todos los casos de conexión para la seguridad del apretón de manos "apretón de manos" entre el cliente y el servidor, se utiliza el protocolo Diffie-Hellmann.


  • Autenticación de usuario externo


    Para simplificar el control sobre las conexiones de los usuarios, en lugar de un esquema con su propia PKI, puede usar un esquema con autenticación de usuario externo mediante inicio de sesión / contraseña . Este esquema es conveniente para autenticar a los usuarios mediante, por ejemplo, un nombre de usuario / contraseña de dominio. Para conectarse al servidor, el certificado del servidor y la clave de firma del paquete HARDENING OPENVPN SECURITY se agregan al archivo de configuración del cliente.
    ejemplo de configuración del cliente


    dev tun proto udp #  IP  OpenVPN remote 172.16.111.166 # Port  port 1200 client resolv-retry infinite tls-client key-direction 1 auth SHA1 cipher BF-CBC #comp-lzo persist-key persist-tun # auth-user-pass c:/temp/pass.txt # # just create a file with name pass.txt # and put to it two lines # ------------- #username #password # ------------- #auth-user-pass verb 3 <ca> -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIJAOt3kFH7PxA0MA0GCSqGSIb3DQEBCwUAMIGjMQswCQYD .... -----END CERTIFICATE----- </ca> <tls-auth> -----BEGIN OpenVPN Static key V1----- 83ddd29fa82212f3059d85a41490134c .... a4f2c7df3a22364a49093bca102dedeb -----END OpenVPN Static key V1----- </tls-auth> 

    Parte de la configuración del servidor para la autenticación del cliente a través del archivo
    Usar métodos de autenticación alternativos


     verify-client-cert none #client-cert-not-required username-as-common-name tls-server tls-auth /usr/local/etc/openvpn/ssl/tlsauth.key key-direction 0 tls-timeout 120 auth SHA1 cipher BF-CBC auth-user-pass-verify /usr/local/etc/openvpn/auth/auth-static-file.pl via-file 

    Este esquema es conveniente, pero muy inseguro.


  • PAM


    Para aumentar la seguridad, puede usar complementos que proporcionen verificación de inicio de sesión / contraseña en sistemas externos. El método más común es el sistema PAM (Módulos de autenticación conectables).
    Agregue la línea al archivo de configuración de OpenVPN


     plugin /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so login 

  • Enrutamiento


    Porque la tarea principal del servidor es proporcionar a los usuarios / servidores remotos acceso a los recursos internos, el servidor le permite determinar el enrutamiento estático de los clientes al servidor y del servidor a los clientes. Desde el punto de vista del acceso del cliente a los recursos internos, el servidor que utiliza DHCP y las directivas "ruta" o "ruta de inserción" le permite transferir rutas de red internas al cliente. Para notificar al servidor sobre las redes remotas en el lado del cliente, se utiliza el "directorio de configuración del cliente" (ccd), un mecanismo que permite usar la directiva "iroute" para describir la lista de redes internas del cliente que deben estar en la tabla de enrutamiento del servidor para transmitir el tráfico hacia ellas.



En este "regular" finalizan las características ampliamente utilizadas y comienza la personalización local para cada caso específico.


Características adicionales de OpenVPN


Considere las características adicionales de OpenVPN, de las cuales alguien puede haber oído hablar, pero en realidad no las ha visto ni usado.


  • Seguridad de red / filtrado de paquetes


    Porque OpenVPN enruta el tráfico, tiene dos modos regulares de operación mutuamente excluyentes. El primer modo es el enrutamiento dentro del servidor OpenVPN, el segundo modo es el enrutamiento nuclear entre interfaces. En el primer caso, OpenVPN es responsable de cambiar y filtrar paquetes entre clientes / redes; en el segundo caso, cualquier filtro de paquetes del sistema admitido en el host (pf, iptables, etc.).
    Pocas personas saben que OpenVPN tiene un filtro de paquetes incorporado que le permite permitir o aislar conexiones entre usuarios y redes.
    Si si. Lo leíste bien. OpenVPN tiene su propio filtro de paquetes incorporado. La capacidad de filtrar el tráfico se implementó en 2010 .
    El filtro de paquetes OpenVPN se controla a través de la interfaz de administración o mediante complementos conectados a OpenVPN.
    Las reglas de tráfico se gestionan a través de un archivo. El formato del archivo es simple.


     [CLIENTS DROP|ACCEPT] {+|-}common_name1 {+|-}common_name2 . . . [SUBNETS DROP|ACCEPT] {+|-}subnet1 {+|-}subnet2 . . . [END] 

    Las directivas de bloque (ACEPTAR / DENEGAR) establecen la acción predeterminada para todos los clientes no especificados dentro del bloque.
    Por ejemplo, archivo para cliente usuario2


     [CLIENTS DROP] +user1 [SUBNETS DROP] [END] 

    bloqueará el tráfico a todos los usuarios y redes, pero permitirá el tráfico al lado del cliente1. Si el usuario1 no describe explícitamente el permiso para transferir tráfico al usuario2, entonces el tráfico irá solo en una dirección usuario2-> usuario1.



U otro ejemplo.
Deshabilite todo excepto el acceso entre usuarios y el servidor DNS ubicado en la red local y el circuito de prueba en la red 192.168.0.0/24


 [CLIENTS DROP] +user1 +user2 [SUBNETS DROP] +10.150.0.1 +10.150.1.1 +192.168.0.0/24 [END] 

El mecanismo de filtrado se activa a través del archivo de configuración, o cuando se conecta el complemento que "establece" el indicador "OPENVPN_PLUGIN_ENABLE_PF".
Discutiremos esta oportunidad más tarde.
El segundo modo de filtrado de tráfico es el filtro de paquetes integrado en el sistema. Para activarlo, la configuración no debe tener una directiva "cliente a cliente". Desde el punto de vista de automatizar la activación / desactivación de las reglas necesarias al conectar / desconectar clientes, es más conveniente usar insertos separados en la lista de reglas, implementadas a través de CHAINS en Iptables (Linux) o en Anchors en PF (FreeBSD). La activación / desactivación de reglas generalmente se realiza a través de las directivas de conexión / desconexión del cliente en el archivo de configuración del servidor, que llama a los scripts correspondientes cuando el usuario se conecta / desconecta.


  • Autenticación PAM avanzada


    La autenticación PAM extendida significa cambiar la lógica del inicio de sesión del usuario y la verificación de contraseña. Esto se logra instalando los complementos apropiados para OpenVPN, que proporcionan lectura y verificación de datos en fuentes externas, o conectando bibliotecas al sistema para escribir cualquier lógica. Una de esas bibliotecas es pam_python , que ayuda a escribir cualquier lógica de verificación de inicio de sesión / contraseña a través de scripts de Python.
    Si se usa, la cadena de verificación del usuario cambia de la siguiente manera.


     plugin openvpn-plugin-auth-pam.so pam_python login USERNAME password PASSWORD domain mydomain.com 

    Dado que "bajo el capó" de PAM son los algoritmos de diálogo del sistema con el usuario o las bibliotecas externas, estos diálogos se pueden controlar. Por ejemplo, conecte tokens OTP al sistema . La biblioteca LinOTP se toma simplemente como un ejemplo, porque Perdí mi propia biblioteca autoescrita durante las pruebas en algún lugar ¯ \ (ツ) / ¯
    Además, los ejemplos se pueden buscar fácilmente en Google con la palabra "pam_python".
    El principal problema cuando se trabaja con módulos PAM externos es la incapacidad de obtener el entorno de sesión OpenVPN dentro del Python llamado o cualquier otro script llamado a través del sistema pam. Es decir el script proporciona solo esas funciones para verificar el nombre de usuario / contraseña que se le asignó.


  • Autenticación diferida


    El servidor OpenVPN admite la llamada autenticación "retrasada". La autenticación "retrasada" se utiliza en los casos en que el servicio de autenticación no puede atender la solicitud de verificación de inicio de sesión / contraseña en tiempo real.


  • Complementos OpenVPN


    Este es un universo paralelo separado, sobre el cual se puede conocer, pero debido a cierta confusión, no pueden o tienen miedo de usarlo. De hecho, escribir un complemento funcional para OpenVPN requiere programación en C con todo lo que implica. Se incluyen ejemplos de complementos simples en el árbol de fuentes de OpenVPN, o por ejemplo, hay un complemento para demostrar las llamadas a métodos de OpenVPN .



Intentemos descubrir cómo funcionan los complementos desde OpenVPN.
Las funciones y parámetros utilizados para trabajar con complementos se describen en un archivo separado
La tarea principal del complemento, cuando es inicializado por el servidor OpenVPN, es transferir la lista de funciones compatibles con el complemento y, al llamar a cualquiera de las funciones, devolver el código de respuesta correcto, que será claro para el servidor.


 #define OPENVPN_PLUGIN_FUNC_SUCCESS 0 #define OPENVPN_PLUGIN_FUNC_ERROR 1 #define OPENVPN_PLUGIN_FUNC_DEFERRED 2 

Detengámonos con más detalle en cada grupo. Consideraremos la lógica del trabajo sobre la base de la autenticación de contraseña del usuario.
Cuando se inicia el servidor, después de leer el archivo de configuración, el servidor llama a las funciones OPENVPN_PLUGIN_UP y OPENVPN_PLUGIN_ROUTE_UP. En el entorno variable de las funciones llamadas, se transfieren los parámetros principales del servidor en ejecución.


 OPENVPN_PLUGIN_UP { "route_netmask_1":"255.255.0.0", "daemon_start_time":"1545994898", "ifconfig_remote":"10.150.0.2", "local_1":"172.16.100.139", "script_context":"init", "config":"/usr/local/etc/openvpn/server150.conf", "link_mtu":"1622", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "verb":"2", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "daemon_log_redirect":"1", "daemon":"1", "route_net_gateway":"172.16.100.1", "dev_type":"tun", "route_gateway_1":"10.150.0.2", "remote_port_1":"1200", "dev":"tun150", "pluginid":"0", "local_port_1":"1200", "route_network_1":"10.150.0.0" } 

 OPENVPN_PLUGIN_ROUTE_UP { "route_netmask_1":"255.255.0.0", "daemon_start_time":"1545994898", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "local_1":"172.16.100.139", "script_context":"init", "config":"/usr/local/etc/openvpn/server150.conf", "link_mtu":"1622", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "verb":"2", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "daemon_log_redirect":"1", "daemon":"1", "route_net_gateway":"172.16.100.1", "dev_type":"tun", "route_gateway_1":"10.150.0.2", "remote_port_1":"1200", "dev":"tun150", "pluginid":"2", "local_port_1":"1200", "route_network_1":"10.150.0.0" } 

Estas funciones se pueden usar para alertas al inicio del servidor o cambios de configuración.
Al conectar un cliente, OpenVPN solicita la capacidad de activar un filtro interno de paquetes.


 OPENVPN_PLUGIN_ENABLE_PF { "route_netmask_1":"255.255.0.0", "daemon_start_time":"1545994898", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "local_1":"172.16.100.139", "script_context":"init", "config":"/usr/local/etc/openvpn/server150.conf", "link_mtu":"1622", "pf_file":"/tmp/openvpn_pf_b7a18ca8fac838679ca87ada6b8a356.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "verb":"2", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "daemon":"1", "daemon_log_redirect":"1", "dev_type":"tun", "route_gateway_1":"10.150.0.2", "remote_port_1":"1200", "dev":"tun150", "pluginid":"11", "local_port_1":"1200", "route_network_1":"10.150.0.0" } 

Como puede ver en el volcado, apareció la variable pf_file. Este archivo debe contener las reglas del filtro de paquetes interno para la sesión actual que se está procesando.
A continuación, el nombre de usuario y la contraseña del usuario se verifican en la función OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY


 OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "IV_NCP":"2", "IV_COMP_STUB":"1", "daemon_start_time":"1545994898", "IV_LZ4":"1", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "link_mtu":"1622", "pf_file":"/tmp/openvpn_pf_b7a18ca8fac838679ca87ada6b8a356.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_a3d0650a43b88ca1b5f305ce2c8f682.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"2", "IV_PLAT":"win", "daemon_pid":"626", "password":"12312312312312", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "dev":"tun150", "pluginid":"5", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

Este es el único lugar donde la contraseña en el entorno variable está presente en claro.
El resultado de esta función debería ser tres posibles respuestas.


 #define OPENVPN_PLUGIN_FUNC_SUCCESS 0 #define OPENVPN_PLUGIN_FUNC_ERROR 1 #define OPENVPN_PLUGIN_FUNC_DEFERRED 2 

Si el servidor recibe una respuesta OPENVPN_PLUGIN_FUNC_DEFERRED, entonces el mecanismo de autenticación "retrasada" entra en funcionamiento. Como vemos, la variable "auth_control_file" apareció en el entorno de la variable, el contenido de esta variable contiene el nombre del archivo en el que se espera una respuesta del sistema de autenticación. La respuesta es el símbolo 0 (para permitir el acceso), 1 (para negar el acceso) colocado en el archivo especificado. El parámetro del servidor "hand-window" determina el tiempo de espera en segundos, durante el cual el servidor esperará una respuesta. Mientras espera, el tráfico de otros clientes no se interrumpe.


Como trabajamos con autenticación de contraseña, no se llama a la función de verificación de certificado OPENVPN_PLUGIN_TLS_VERIFY. En su lugar, se llama a OPENVPN_PLUGIN_TLS_FINAL de inmediato, lo que confirma el establecimiento de la sesión.


 OPENVPN_PLUGIN_TLS_FINAL { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "IV_NCP":"2", "IV_COMP_STUB":"1", "daemon_start_time":"1545994898", "IV_LZ4":"1", "redirect_gateway":"0", "ifconfig_remote":"10.150.0.2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "link_mtu":"1622", "pf_file":"/tmp/openvpn_pf_b7a18ca8fac838679ca87ada6b8a356.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_a3d0650a43b88ca1b5f305ce2c8f682.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"2", "IV_PLAT":"win", "daemon_pid":"626", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "dev":"tun150", "pluginid":"10", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

A continuación, se llama a la llamada OPENVPN_PLUGIN_IPCHANGE, que se llama antes de cambiar la dirección IP del cliente.


 OPENVPN_PLUGIN_IPCHANGE { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "trusted_ip":"172.16.111.168", "link_mtu":"1622", "IV_COMP_STUB":"1", "daemon_start_time":"1547319280", "IV_LZ4":"1", "redirect_gateway":"0", "common_name":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "ifconfig_remote":"10.150.0.2", "IV_NCP":"2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "trusted_port":"1200", "pf_file":"/tmp/openvpn_pf_4fcad505693b33f97c4fe105df8681cb.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_321bb12075dc0e1b5440d227220bac5d.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"3", "IV_PLAT":"win", "daemon_pid":"52435", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "dev":"tun150", "pluginid":"3", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

Se llama a la función OPENVPN_PLUGIN_CLIENT_CONNECT_V2 cuando el servidor DHCP interno establece la dirección IP.


 OPENVPN_PLUGIN_CLIENT_CONNECT_V2 { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "trusted_ip":"172.16.111.168", "link_mtu":"1622", "IV_COMP_STUB":"1", "daemon_start_time":"1547319280", "IV_LZ4":"1", "dev":"tun150", "common_name":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "time_ascii":"Sat Jan 12 18:54:48 2019", "ifconfig_remote":"10.150.0.2", "IV_NCP":"2", "untrusted_port":"1200", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "trusted_port":"1200", "pf_file":"/tmp/openvpn_pf_4fcad505693b33f97c4fe105df8681cb.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_321bb12075dc0e1b5440d227220bac5d.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"3", "IV_PLAT":"win", "daemon_pid":"52435", "time_unix":"1547319288", "redirect_gateway":"0", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "remote_port_1":"1200", "ifconfig_pool_local_ip":"10.150.0.5", "pluginid":"9", "ifconfig_pool_remote_ip":"10.150.0.6", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

En un entorno variable, aparecen variables que contienen los parámetros del túnel "ifconfig_pool_local_ip" e "ifconfig_pool_remote_ip".


La función OPENVPN_PLUGIN_LEARN_ADDRESS se llama cuando el servidor OpenVPN aprende la conexión de las direcciones IP y se dirige a ellas. Después de salir de esta función, se activa el procedimiento para aplicar la configuración del filtro de paquetes desde el archivo. La variable de entorno OPENVPN_PLUGIN_LEARN_ADDRESS en este caso corresponde a la fase OPENVPN_PLUGIN_CLIENT_CONNECT_V2.


 fa56bf61-.../172.16.111.168:1200 ----- pf_check_reload : struct pf_context ----- fa56bf61-.../172.16.111.168:1200 enabled=1 fa56bf61-.../172.16.111.168:1200 filename='/tmp/openvpn_pf_343330698e4acdea34c8a8c7fb87d861.tmp' fa56bf61-.../172.16.111.168:1200 file_last_mod=1547319124 fa56bf61-.../172.16.111.168:1200 n_check_reload=1 fa56bf61-.../172.16.111.168:1200 reload=[1,15,1547319125] fa56bf61-.../172.16.111.168:1200 ----- struct pf_set ----- fa56bf61-.../172.16.111.168:1200 kill=0 fa56bf61-.../172.16.111.168:1200 ----- struct pf_subnet_set ----- fa56bf61-.../172.16.111.168:1200 default_allow=ACCEPT fa56bf61-.../172.16.111.168:1200 ----- struct pf_cn_set ----- fa56bf61-.../172.16.111.168:1200 default_allow=DROP fa56bf61-.../172.16.111.168:1200 12345678-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 fa56bf61-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 ---------- fa56bf61-.../172.16.111.168:1200 fa56bf61-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 12345678-90da-11e8-bf33-005056a12a82-1234567 ACCEPT fa56bf61-.../172.16.111.168:1200 -------------------- 

Cuando se desconecta un cliente, se llama a la función OPENVPN_PLUGIN_CLIENT_DISCONNECT.


 OPENVPN_PLUGIN_CLIENT_DISCONNECT { "route_netmask_1":"255.255.0.0", "route_gateway_1":"10.150.0.2", "trusted_ip":"172.16.111.168", "link_mtu":"1622", "IV_COMP_STUB":"1", "daemon_start_time":"1547319280", "IV_LZ4":"1", "dev":"tun150", "common_name":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "time_ascii":"Sat Jan 12 18:54:48 2019", "bytes_received":"30893", "IV_NCP":"2", "untrusted_port":"1200", "ifconfig_remote":"10.150.0.2", "IV_LZ4v2":"1", "local_1":"172.16.100.139", "script_context":"init", "untrusted_ip":"172.16.111.168", "config":"/usr/local/etc/openvpn/server150.conf", "username":"fa56bf61-90da-11e8-bf33-005056a12a82-1234568", "trusted_port":"1200", "pf_file":"/tmp/openvpn_pf_4fcad505693b33f97c4fe105df8681cb.tmp", "ifconfig_local":"10.150.0.1", "tun_mtu":"1500", "auth_control_file":"/tmp/openvpn_acf_4bdddbada2885cde42cd3cb1b85d77e5.tmp", "daemon":"1", "IV_COMP_STUBv2":"1", "verb":"3", "IV_PLAT":"win", "daemon_pid":"52435", "time_unix":"1547319288", "redirect_gateway":"0", "route_vpn_gateway":"10.150.0.2", "proto_1":"udp", "route_net_gateway":"172.16.100.1", "IV_PROTO":"2", "daemon_log_redirect":"1", "time_duration":"3781", "dev_type":"tun", "IV_VER":"2.4.3", "IV_LZO":"1", "bytes_sent":"22684", "remote_port_1":"1200", "ifconfig_pool_local_ip":"10.150.0.5", "pluginid":"7", "ifconfig_pool_remote_ip":"10.150.0.6", "local_port_1":"1200", "IV_TCPNL":"1", "route_network_1":"10.150.0.0" } 

En un entorno variable, se agregan la duración de la conexión y el tráfico de usuarios.


Como puede ver, debido a la abundancia de datos en diferentes llamadas, escribir y depurar un complemento en el lenguaje de programación C (C ++) será una tarea que llevará mucho tiempo.
Para expandir la funcionalidad, se decidió hacer un "milagro" primero para el proyecto interno y luego ponerlo en el dominio público :)
Después de una larga lectura de los códigos fuente de OpenVPN y varios ejemplos de complementos altamente especializados, se escribió un proyecto que utiliza Python como lenguaje de programación para la lógica de procesamiento de la sesión. El código es un complemento en el lenguaje C que se conecta a OpenVPN, que envía todas las solicitudes al complemento, envía el módulo a Python a través de la referencia c-api .


OpenVPN plugin proxy de python


¿Por qué es el módulo Python?


La referencia de Python c-api que trabaja directamente con archivos de python no funciona correctamente al cargar bibliotecas de python.


Como funciona


Cuando el complemento se inicializa en OpenVPN, el complemento devuelve una lista enmascarada de todas las funciones que puede servir. Cuando se produce la siguiente fase de conexión o evento interno, OpenVPN llama a las funciones correspondientes desde el complemento. El complemento convierte la variable de entorno y los parámetros pasados ​​a la función en una estructura, inicializa python y pasa la estructura al procedimiento correspondiente del módulo python. El procedimiento devuelve una de las tres respuestas al complemento (0 - Correcto, 1 - Error, 2 - Diferido). La respuesta es transformada y devuelta por OpenVPN.


Tenga en cuenta que todas las llamadas al módulo son "sin estado", lo que significa que los procedimientos no recuerdan y no saben lo que sucedió anteriormente en otras llamadas. Solo puede enfocarse en el entorno variable pasado al complemento desde OpenVPN.


Dentro del módulo python, puede implementar cualquier lógica conectando las bibliotecas y recursos necesarios. Si no está seguro de la velocidad de las verificaciones, utilice las confirmaciones "pendientes".


Usando la agrupación de usuarios conectados al servicio, a través de pf_file puede ajustar la interacción de la red entre los usuarios y otros recursos. A su vez, al conectar el complemento de monitoreo, siempre será posible administrar sesiones de clientes a través de la interfaz de administración de OpenVPN.


Durante la prueba del proyecto, se desarrolló un mecanismo de generación de contraseña, similar a los tokens jwt, pero con un tamaño más pequeño.


El punto es simple. El token contiene el identificador del cliente y la fecha de vencimiento del acceso. Para firmar el token, se utiliza HMAC_SHA1 con una clave privada. Después de firmar el token, la firma corrompe el contenido de texto y lo convierte en base64. De este modo, se obtiene el "sellado" de la ficha. Se utiliza un token sellado como contraseña del usuario. Si se produce un cambio no autorizado de un bloque de datos, xor se rompe, si xor se rompe, entonces se rompe la verificación de firma. Sin una clave privada, la firma no se puede cambiar.


Si no desea controlar el tiempo de validez de la contraseña con sus manos, genere dicho token y verifique la validez dentro del complemento sin llamar a servicios externos. Este esquema es muy conveniente para la generación de contraseña de sesión durante un tiempo determinado. Al mismo tiempo, puede transferir el contenido del token a un sistema de control externo y se configurará para desconectar al usuario una vez que el token caduque.


Espero que la información de este artículo te haya sido útil.
Gracias por tomarse el tiempo de leerlo.
Si tiene preguntas, intentaré responder lo que pueda.


© Aborche 2019
Aborche

Source: https://habr.com/ru/post/es435802/


All Articles