Tag: ubuntu

  • Configuração de servidor OpenVPN

    OpenVPN é um sistema de rede virtual privada (VPN), usado pra criar conexões seguras entre dispositivos, protegendo a troca de informações mesmo em trajetos não confiáveis, como a internet. Implementa tanto aplicação de servidor quanto de cliente e é distribuído sob a licença GPL-2.0.

    O sistema funciona com base em infraestrutura de chave pública (PKI). Pra configurar a autenticação de forma segura é necessário gerar certificados SSL e chaves para uma autoridade certificadora (CA), para o servidor e para os clientes da VPN.

    Felizmente, não precisamos tocar diretamente no OpenSSL, que é bem complexo. Em vez disso, a gente usa o EasyRSA, uma ferramenta que nos ajuda a gerar as chaves e certificados que a gente precisa.

    Considerando uma instalação do Debian ou Ubuntu server:

    # apt install openvpn easy-rsa

    Pra facilitar e deixar a configuração organizada, copie a pasta do EasyRSA para dentro da pasta de configuração do OpenVPN.

    # cp -r /usr/share/easy-rsa /etc/openvpn/

    Vá para a pasta /etc/openvpn/easy-rsa, edite copie o arquivo vars.example como var e descomente as linhas que quiser editar de acordo com a sua preferência. Configurações sugeridas:

    set_var EASYRSA_KEY_SIZE        4096
    set_var EASYRSA_CERT_EXPIRE     731
    set_var EASYRSA_CRL_DAYS        366
    set_var  EASYRSA_FIX_OFFSET 30

    Dessa forma, os certificados serão válidos por 2 anos, a lista de revogação de certificados (CRL) por 1 ano, e todos os certificados vão ser emitidos com validade fixa a partir de 30 de Janeiro.

    Após configurado, podemos iniciar nossa PKI e gerar o CA:

    # bash easyrsa init-pki
    # bash easyrsa build-ca

    Ao gerar a chave do CA, uma senha será pedida pra criptografar a chave do CA.

    Deve-se também gerar a chave de Diffie-Hellman, que é usada para gerar a chave simétrica da conexão de VPN a ser estabelecida.

    # bash easyrsa gen-dh

    Opcionalmente, para maior segurança, pode-se gerar uma chave de autenticação para que o servidor exija uma assinatura válida nos pacotes recebidos dos clientes.

    # openvpn --genkey secret pki/tls-auth.key

    Ao gerar o par de chaves do servidor, é uma boa ideia gerar a chave sem senha pra que o serviço possa ser iniciado junto com o sistema:

    # bash easyrsa build-server-full nome_do_servidor nopass

    A senha da chave do CA ainda será pedida para assinar o certificado do servidor.

    Assim como para o servidor, você pode escolher deixar as chaves dos clientes com senha ou não passando o parâmetro opcional nopass.

    # bash easyrsa build-client-full nome_do_cliente0 nopass

    Agora, a configuração do servidor e dos clientes vai depender do propósito da VPN: pode ser um gateway, pode ser apenas para conectar um cliente ao outro, pode ser pra conectar clientes à uma LAN.

    Crie um arquivo com extensão .conf na pasta /etc/openvpn server, como por exemplo config_do_servidor.conf com esse conteúdo de exemplo – adapte-o para a sua necessidade:

    # Configurações da conexão
    # Descomente a linha abaixo e coloque o IP do seu servidor caso ele esteja dentro de uma LAN
    ;local 192.168.0.10
    port 1194
    proto udp4
    dev tun0
    keepalive 10 120
    persist-key
    persist-tun
    
    # As linhas abaixo determinam a rede privada que seu servidor vai criar
    server 10.8.0.0 255.255.255.0
    topology subnet
    push "route 10.8.0.0 255.255.255.0"
    
    # Descomente a linha abaixo e substitua a LAN pela sua caso queira que os clientes tenham uma rota para a LAN do servidor
    ;push "route 192.168.0.0 255.255.255.0"
    
    # Descomente a linha abaixo caso queira que o cliente use o servidor de VPN como gateway
    ;push "redirect-gateway def1 bypass-dhcp"
    
    # Configura resolvedores de DNS alternativos
    ;push "dhcp-option DNS 208.67.222.222"
    ;push "dhcp-option DNS 208.67.220.220"
    
    # Permite que clientes da VPN possam alcançar outros
    ;client-to-client
    
    # Limita o número de clientes na VPN
    ;max-clients 5
    
    # Configurações do processo
    verb 3
    explicit-exit-notify 1
    status /var/log/openvpn/status-conext00.log
    # Reduz o privilégio de execução após inicialização para o usuário e grupo abaixo - em distribuições da família Fedora e Red Hat, existe um usuário openvpn próprio. O grupo nogroup não existe.
    user nobody
    group nogroup
    # Mantém clientes com o mesmo IP na VPN
    ;ifconfig-pool-persist /var/log/openvpn/ipp.txt
    
    # Certificados e chaves necessários gerados através do easy-rsa
    ca ../easy-rsa/pki/ca.crt
    cert ../easy-rsa/pki/issued/nome_do_servidor.crt
    key ../easy-rsa/pki/private/nome_do_servidor.key
    dh ../easy-rsa/pki/dh.pem
    
    # Lista opcional de revogação de certificados
    ;crl-verify ../easy-rsa/pki/crl.pem
    
    # Chave TLS opcional para maior segurança, exigindo que pacotes recebidos tenham uma assinatura válida
    ;tls-auth ../easy-rsa/pki/tls-auth.key 0
    

    Observe que as linhas do tipo

    push "algum parâmetro"

    são configurações que também podem ser especificadas no arquivo de configuração do cliente em vez do servidor.

    Precisa-se também configurar as permissões de firewall e habilitar no kernel o encaminhamento em IPv4.

    Para habilitar o encaminhamento no kernel, adicione um arquivo /etc/sysctl.d/98-ip-fwd.conf com a seguinte linha:

    net.ipv4.ip_forward=1

    Reinicie para que tenha efeito ou

    # sysctl -w net.ipv4.ip_forward=1

    No firewall, para permitir conexão de clientes:

    # ufw allow 1194/udp

    Caso use o servidor de VPN como um gateway ou estabeleça rota do cliente para a LAN em que o servidor está:

    # ufw route allow in on tun0 out on eth0
    # ufw route allow in on eth0 out on tun0

    E configure o protocolo NAT adicionando este trecho no topo do arquivo /etc/ufw/before.rules

    ### START OF MANUAL NAT CONFIG
    # NAT table rules
    *nat
    :POSTROUTING ACCEPT [0:0]
    
    # Forward traffic through eth0 - Change to match you out-interface
    -A POSTROUTING -s 10.8.0.0/24 -o tun0 -j MASQUERADE
    
    # don't delete the 'COMMIT' line or these nat table rules won't
    # be processed
    COMMIT
    ### END OF MANUAL NAT CONFIG

    Lembre-se de substituir a interface física e a rede pelas do seu servidor.

    Alternativamente ao NAT, no caso da existência de uma LAN, você pode configurar no seu roteador uma rota para 10.8.0.0/24 pelo IP privado do seu servidor.

    Agora basta habilitar e iniciar o serviço:

    # systemctl enable --now openvpn-server@config_do_servidor.service

    É isso, o servidor deve estar funcionando.

    Agora precisamos que clientes se conectem. Pra isso, eles precisam de um arquivo de configuração do mesmo tipo que foi feito para o servidor. O easy-rsa não gera esses arquivos, então eu fiz um pequeno script pra resolver esse problema, que deixo em /etc/openvpn/easy-rsa/build-client-config.sh

    Conteúdo do script:

    #!/bin/bash
    
    system=$1
    client=$2
    clients_dir=./clients
    client_template_win=./clients/client.ovpn
    client_template_lnx=./clients/client.conf
    
    
    init() {
            mkdir $clients_dir
    cat <<'EOF' > $client_template_win
    client
    dev tun
    proto udp4
    remote servidor.exemplo.com 1194
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    remote-cert-tls server
    ;key-direction 1
    verb 3
    EOF
    
    cat <<'EOF' > $client_template_lnx
    client
    dev tun
    proto udp4
    remote servidor.exemplo.com 1194
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    remote-cert-tls server
    ;key-direction 1
    verb 3
    user nobody
    group nogroup
    EOF
    
            if ! [[ -f ./pki/ca.crt ]]; then
                    echo "CA não encontrado. Encerrando."
                    exit 1
            else
                    echo "" | tee -a $client_template_lnx $client_template_win
                    echo "<ca>" | tee -a $client_template_lnx $client_template_win
                    cat pki/ca.crt | tee -a $client_template_lnx $client_template_win
                    echo "</ca>" | tee -a $client_template_lnx $client_template_win
            fi
    
            if [[ -f ./pki/tls-auth.key ]]; then
                    sed -i 's/;//g' $client_template_lnx $client_template_win
                    echo "" | tee -a $client_template_lnx $client_template_win
                    echo "<tls-auth>" | tee -a $client_template_lnx $client_template_win
                    cat pki/tls-auth.key | tee -a $client_template_lnx $client_template_win
                    echo  "</tls-auth>" | tee -a $client_template_lnx $client_template_win
            else
                    echo "tls-auth.key não encontrada, prosseguindo sem"
            fi
    }
    
    if ! [[ -d $clients_dir ]]; then
            init
            exit
    fi
    
    if ! [[ -f ./pki/issued/$client.crt ]]; then
            echo "Cliente não existe"
            exit 1
    fi
    
    if [[ $system == "-l" || $system == "--linux" ]]; then
            fileExt=conf
    elif [[ $system == "-o" || $system == "--outro" ]]; then
            fileExt=ovpn
    else
            echo "Sistema não especificado"
    fi
    
    targetFile=clients/$client.$fileExt
    
    cp clients/client.$fileExt $targetFile
    
    echo "" | tee -a $targetFile
    echo "<cert>" | tee -a $targetFile
    cat pki/issued/$client.crt | tee -a $targetFile
    echo "</cert>" | tee -a $targetFile
    
    echo "" | tee -a $targetFile
    echo "<key>" | tee -a $targetFile
    cat pki/private/$client.key | tee -a $targetFile
    echo "</key>" | tee -a $targetFile

    Pra inicializar, basta executar o script sem nenhum argumento

    # bash build-client-config.sh

    Ele vai criar uma pasta clients, com um template para Linux, client.conf, e outro para Windows, client.ovpn. Edite-os conforme necessário.

    Feito isso, é possível criar o arquivo de configuração para um cliente existente com

    # bash build-client-config.sh --linux nome_do_cliente0

    ou para Windows, macOS, iOS ou Android

    # bash build-client-config.sh --outro nome_do_cliente0