OpenVPN, quanto nesta palavra. Um servidor VPN de código aberto gratuito, com várias plataformas, configurável de maneira flexível e flexível, que na verdade é o padrão padrão para organizar o acesso a redes corporativas internas. A maioria dos administradores o usa com configurações padrão ou com configurações típicas amplamente descritas em diferentes HOW-TOs. Mas o OpenVPN é tão simples quanto parece à primeira vista? Neste artigo, consideraremos os mecanismos internos do OpenVPN, ocultos aos olhos, que alteram drasticamente a ideia de suas capacidades.
O servidor OpenVPN é distribuído na forma de código-fonte ou pacotes compilados prontos para instalar para vários sistemas operacionais. O OpenSSL é usado como uma biblioteca que fornece criptografia.
A maioria das configurações para conectar clientes ao servidor, bem como entre servidores, envolve o uso de várias chaves privadas ou privadas / públicas para garantir a segurança do tráfego interno. Para redes corporativas no modo MultiPoint-para-SinglePoint, geralmente é usada uma autoridade de certificação PKI, fácil de construir usando easy-rsa ou XCA . Para comunicação entre servidores ponto a ponto, uma configuração de chave compartilhada é usada principalmente. Lembre-se dos mecanismos e recursos básicos e conhecidos.
Principais mecanismos e capacidades
- Autenticação de certificado
 - Uma enorme quantidade de documentação foi escrita sobre isso. O ponto é simples. Está sendo criada uma autoridade de certificação que emite certificados de usuário. Com a ajuda de uma autoridade de certificação, é fornecido controle para conectar usuários ao servidor OpenVPN. Quando o certificado expira ou é revogado, o acesso do usuário é bloqueado. As chaves privadas com uma senha definida nelas, emitida em conjunto com o certificado, fornecem segurança contra conexões não autorizadas a recursos internos. 
 
- Chaves ponto a ponto privadas
 - Do ponto de vista de conectar apenas um usuário / servidor aos recursos da empresa, um esquema com chaves privadas é usado. Uma chave é gerada em um dos hosts, que é compartilhado entre o servidor e o cliente. 
 
Em todos os casos de conexão para segurança do handshake "handshake" entre o cliente e o servidor, o protocolo Diffie-Hellmann é usado.
- Autenticação de usuário externo
 - Para simplificar o controle sobre as conexões do usuário, em vez de um esquema com sua própria PKI, você pode usar um esquema com autenticação de usuário externo por login / senha . Esse esquema é conveniente para autenticar usuários por, digamos, um login / senha de domínio. Para conectar-se ao servidor, o certificado do servidor e a chave de assinatura do pacote HARDENING OPENVPN SECURITY são adicionados ao arquivo de configuração do cliente.
 exemplo de configuração do 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 da configuração do servidor para autenticação do cliente via arquivo
 Usando métodos de autenticação 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
 
 - Esse esquema é conveniente, mas muito inseguro. 
 
- PAM
 - Para aumentar a segurança, você pode usar plug-ins que fornecem verificação de login / senha em sistemas externos. O método mais comum é o PAM do sistema (Módulos de autenticação conectáveis).
 Adicione a linha ao arquivo de configuração OpenVPN
 
 -  - plugin /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so login
 
 
- Encaminhamento
 - Porque A principal tarefa do servidor é fornecer aos usuários / servidores remotos acesso a recursos internos; o servidor permite determinar o roteamento estático dos clientes para o servidor e do servidor para os clientes. Do ponto de vista do acesso do cliente aos recursos internos, o servidor que usa DHCP e as diretivas "rota" ou "rota de envio" permitem transferir rotas de rede internas para o cliente. Para notificar o próprio servidor sobre redes remotas no lado do cliente, é usado "dir de configuração do cliente" (ccd), um mecanismo que permite usar a diretiva "iroute" para descrever a lista de redes internas do cliente que devem estar na tabela de roteamento do servidor para trafegar o tráfego para elas. 
 
Nesse recurso "comum", amplamente utilizado, termina a personalização local e final para cada caso específico.
Recursos adicionais do OpenVPN
Considere os recursos adicionais do OpenVPN, dos quais alguém já deve ter ouvido falar, mas, na realidade, não viu ou usou.
- Segurança de rede / filtragem de pacotes
 - Porque O OpenVPN direciona o tráfego, possui dois modos de operação regulares mutuamente exclusivos. O primeiro modo é o roteamento dentro do servidor OpenVPN, o segundo modo é o roteamento nuclear entre interfaces. No primeiro caso, o OpenVPN é responsável por alternar e filtrar pacotes entre clientes / redes; no segundo caso, qualquer filtro de pacote do sistema suportado no host (pf, iptables, etc).
 Poucas pessoas sabem que o OpenVPN possui um filtro de pacotes interno que permite permitir ou isolar conexões entre usuários e redes.
 Sim sim Você leu certo. O OpenVPN possui seu próprio filtro de pacotes embutido. A capacidade de filtrar o tráfego foi implementada em 2010 .
 O filtro de pacotes OpenVPN é controlado pela interface de gerenciamento ou por plug-ins conectados ao OpenVPN.
 As regras de tráfego são gerenciadas através de um arquivo. O formato do arquivo é simples.
 
 -  - [CLIENTS DROP|ACCEPT] {+|-}common_name1 {+|-}common_name2 . . . [SUBNETS DROP|ACCEPT] {+|-}subnet1 {+|-}subnet2 . . . [END]
 
 - As diretivas de bloco (ACCEPT / DENY) definem a ação padrão para todos os clientes não especificados dentro do bloco.
 Por exemplo, arquivo para o usuário user2
 
 -  - [CLIENTS DROP] +user1 [SUBNETS DROP] [END]
 
 - bloqueará o tráfego para todos os usuários e redes, mas permitirá o tráfego para o cliente1. Se o usuário1 não descrever explicitamente a permissão para transferir tráfego para o usuário2, o tráfego seguirá apenas em uma direção user2-> user1. 
 
Ou outro exemplo.
Desative tudo, exceto o acesso entre usuários e o servidor DNS localizado na rede local e o circuito de teste na rede 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] 
O mecanismo de filtragem é ativado por meio do arquivo de configuração ou ao conectar o plug-in que "define" o sinalizador "OPENVPN_PLUGIN_ENABLE_PF".
Discutiremos essa oportunidade mais tarde.
O segundo modo de filtragem de tráfego é o filtro de pacotes embutido no sistema. Para ativá-lo, a configuração não deve ter uma diretiva "cliente para cliente". Do ponto de vista da automação da ativação / desativação das regras necessárias ao conectar / desconectar clientes, é mais conveniente usar inserções separadas na lista de regras, implementadas por meio de CHAINS in Iptables (Linux) ou em Anchors in PF (FreeBSD). A ativação / desativação de regras geralmente é feita por meio das diretivas de conexão / desconexão do cliente no arquivo de configuração do servidor, que chamam os scripts correspondentes quando o usuário se conecta / desconecta.
- Autenticação avançada de PAM
 - A autenticação estendida do PAM significa alterar a lógica do login do usuário e da verificação de senha. Isso é obtido instalando os plug-ins apropriados para o OpenVPN, que fornecem leitura e verificação de dados em fontes externas, ou conectando bibliotecas ao sistema que permitem que qualquer lógica seja script. Uma dessas bibliotecas é o pam_python , que ajuda a criar scripts para qualquer lógica de verificação de login / senha por meio de scripts Python.
 Se for usada, a sequência de verificação do usuário será alterada da seguinte maneira.
 
 -  - plugin openvpn-plugin-auth-pam.so pam_python login USERNAME password PASSWORD domain mydomain.com
 
 - Como o “under the hood” do PAM são os algoritmos de diálogo do sistema com o usuário ou as bibliotecas externas, esses diálogos podem ser controlados. Por exemplo, conecte tokens OTP ao sistema . A biblioteca LinOTP é tomada simplesmente como exemplo, porque Perdi minha própria biblioteca auto-escrita durante os testes em algum lugar ¯ \ (ツ) / ¯
 Além disso, os exemplos são facilmente pesquisados pela palavra "pam_python".
 O principal problema ao trabalhar com módulos PAM externos é a incapacidade de obter o ambiente de sessão do OpenVPN dentro do Python chamado ou qualquer outro script chamado através do pam do sistema. I.e. o script fornece apenas as funções para verificar o login / senha atribuídos a ele.
 
 
- Autenticação Adiada
 - O servidor OpenVPN suporta a chamada autenticação "atrasada". A autenticação "atrasada" é usada nos casos em que o serviço de autenticação não pode atender à solicitação de verificação de login / senha em tempo real. 
 
- Plugins OpenVPN
 - Este é um universo paralelo separado, sobre o qual pode ser conhecido, mas, devido a alguma confusão, eles não conseguem ou têm medo de usar. De fato, escrever um plug-in funcional para o OpenVPN requer programação em C com tudo o que isso implica. Exemplos de plugins simples estão incluídos na árvore de código-fonte do OpenVPN ou , por exemplo, existe um plug - in para demonstrar as chamadas de método do OpenVPN . 
 
Vamos tentar descobrir como os plugins funcionam no OpenVPN.
Funções e parâmetros usados para trabalhar com plugins são descritos em um arquivo separado
A principal tarefa do plug-in, quando é inicializada pelo servidor OpenVPN, é transferir a lista de funções suportadas pelo plug-in e, ao chamar qualquer uma das funções, retornar o código de resposta correto, que ficará claro para o servidor.
 #define OPENVPN_PLUGIN_FUNC_SUCCESS 0 #define OPENVPN_PLUGIN_FUNC_ERROR 1 #define OPENVPN_PLUGIN_FUNC_DEFERRED 2 
Vamos nos aprofundar mais em cada grupo. Vamos considerar a lógica do trabalho com base na autenticação de senha do usuário.
Quando o servidor inicia, após a leitura do arquivo de configuração, o servidor chama as funções OPENVPN_PLUGIN_UP e OPENVPN_PLUGIN_ROUTE_UP. No ambiente variável das funções chamadas, os principais parâmetros do servidor em execução são transferidos.
 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" } 
Essas funções podem ser usadas para alertas na inicialização do servidor ou alterações na configuração.
Ao conectar um cliente, o OpenVPN solicita a capacidade de ativar um filtro de pacotes interno.
 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 você pode ver no dump, a variável pf_file apareceu. Este arquivo deve conter as regras do filtro de pacotes interno para a sessão atual que está sendo processada.
Em seguida, o nome de usuário e a senha do usuário são verificados na função 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 é o único local em que a senha no ambiente variável está presente de forma clara.
O resultado desta função deve ser três respostas possíveis.
 #define OPENVPN_PLUGIN_FUNC_SUCCESS 0 #define OPENVPN_PLUGIN_FUNC_ERROR 1 #define OPENVPN_PLUGIN_FUNC_DEFERRED 2 
Se o servidor receber uma resposta OPENVPN_PLUGIN_FUNC_DEFERRED, o mecanismo de autenticação "atrasada" entra em operação. Como vemos, a variável "auth_control_file" apareceu no ambiente da variável, o conteúdo dessa variável contém o nome do arquivo no qual uma resposta do sistema de autenticação será esperada. A resposta é o símbolo 0 (para permitir acesso), 1 (para negar acesso) colocado no arquivo especificado. O parâmetro do servidor "janela manual" determina o tempo limite em segundos, durante os quais o servidor aguardará uma resposta. Enquanto aguarda, o tráfego de outros clientes não é interrompido.
Como trabalhamos com autenticação de senha, a função de verificação de certificado OPENVPN_PLUGIN_TLS_VERIFY não é chamada. Em vez disso, OPENVPN_PLUGIN_TLS_FINAL é chamado imediatamente, confirmando o estabelecimento da sessão.
 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" } 
Em seguida, é chamada a chamada OPENVPN_PLUGIN_IPCHANGE, que é chamada antes de alterar o endereço IP do 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" } 
A função OPENVPN_PLUGIN_CLIENT_CONNECT_V2 é chamada quando o endereço IP é definido pelo servidor DHCP interno.
 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" } 
Em um ambiente variável, as variáveis aparecem contendo os parâmetros do túnel "ifconfig_pool_local_ip" e "ifconfig_pool_remote_ip".
A função OPENVPN_PLUGIN_LEARN_ADDRESS é chamada quando o servidor OpenVPN aprende a conexão de endereços IP e as rotas para eles. Depois de sair dessa função, o procedimento para aplicar as configurações do filtro de pacotes do arquivo é ativado. A variável de ambiente OPENVPN_PLUGIN_LEARN_ADDRESS nesse caso corresponde à 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 -------------------- 
Quando um cliente é desconectado, a função OPENVPN_PLUGIN_CLIENT_DISCONNECT é chamada.
 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" } 
Em um ambiente variável, a duração da conexão e o tráfego do usuário são adicionados.
Como você pode ver, devido à abundância de dados em diferentes chamadas, escrever e depurar um plug-in na linguagem de programação C (C ++) será uma tarefa bastante demorada.
Para expandir a funcionalidade, decidiu-se fazer um "milagre" primeiro para o projeto interno e depois publicá-lo :)
Após uma longa leitura dos códigos fonte do OpenVPN e vários exemplos de plugins altamente especializados, foi criado um projeto que usa o Python como a linguagem de programação para a lógica de processamento da sessão. O código é um plug-in na linguagem C que se conecta ao OpenVPN, que envia todas as solicitações ao plug-in, envia o módulo para Python através da referência c-api .
OpenVPN plugin proxy python
Por que o módulo Python?
A referência c-api do Python, trabalhando diretamente com arquivos python, não funciona corretamente com o carregamento de bibliotecas python.
Como isso funciona?
Quando o plugin é inicializado no OpenVPN, ele retorna uma lista mascarada de todas as funções que ele pode servir. Quando a próxima fase da conexão ou evento interno ocorrer, o OpenVPN chama as funções correspondentes do plug-in. O plug-in converte a variável de ambiente e os parâmetros passados para a função em uma estrutura, inicializa o python e passa a estrutura para o procedimento correspondente do módulo python. O procedimento retorna uma das três respostas ao plug-in (0 - Sucesso, 1 - Erro, 2 - Adiado). A resposta é transformada e retornada pelo OpenVPN.
Observe que todas as chamadas do módulo são "sem estado", o que significa que os procedimentos não se lembram e não sabem o que aconteceu anteriormente em outras chamadas. Você pode focar apenas no ambiente variável passado para o plug-in do OpenVPN.
Dentro do módulo python, você pode implementar qualquer lógica conectando as bibliotecas e os recursos necessários. Se você não tiver certeza da velocidade das verificações, use as confirmações "pendentes".
Usando o agrupamento de usuários conectados ao serviço, através do pf_file, você pode ajustar bastante a interação da rede entre usuários e outros recursos. Por sua vez, conectando o plug-in para monitoramento, sempre será possível gerenciar sessões do cliente por meio da interface de gerenciamento OpenVPN.
Durante o teste do projeto, um mecanismo de geração de senha foi desenvolvido, semelhante aos tokens jwt, mas com um tamanho menor.
O ponto é simples. O token contém o identificador do cliente e a data de validade do acesso. Para assinar o token, é utilizado o HMAC_SHA1 com uma chave privada. Após a assinatura do token, o conteúdo do texto é corrompido pela assinatura e convertido em base64. Assim, a "vedação" do token é obtida. Um token selado é usado como senha do usuário. Se ocorrer uma alteração não autorizada de um bloco de dados, xor interrompe, se xor interrompe, a verificação de assinatura é interrompida. Sem uma chave privada, a assinatura não pode ser alterada.
Se você não deseja controlar manualmente o horário da senha, gere esse token e verifique a validade dentro do plug-in sem chamar serviços externos. Esse esquema é muito conveniente para a geração de senha da sessão por um determinado período. Ao mesmo tempo, você pode transferir o conteúdo do token para um sistema de controle externo e ele se configurará para desconectar o usuário após a expiração do token.
Espero que as informações neste artigo tenham sido úteis para você.
Obrigado por reservar um tempo para lê-lo.
Se você tiver alguma dúvida, tentarei responder o que puder.
© Aborche 2019
