\documentclass[11pt,a4paper]{article} \usepackage[portuguese]{babel} \usepackage[lining]{ebgaramond} \usepackage{style} \setlength{\parindent}{0em} \setlength{\parskip}{2ex} \title{Practical Assignment \#2} \author{ João Neto -- 2023234004\\[1em] Vasco Alves -- 2022228207 } \begin{document} \maketitle \tableofcontents \newpage \section{Introdução} Este projeto tem como âmbito implementar, uma rede virtual privada (VPN) num cenário de road-warrior, configurar \textit{two-factor authentication} (2FA) com os serviços OpenVPN e Apache, e gerir certificados X.509 utilizando OCSP. % NOTE(vasco): Eu acho que basta explicar o cenario e explicar como decidimos % implementar <- yeah agree, also esta introdução acho que é boa fala sobre o objetivo % e o cenario, e porque é que o nosso cenario é como é. Não sei se a parte das razões de %segurança devia estar nesta parte ou na conclusão como perpetiva futura e reflexão, mas aqui %também não está mal. % Para tal, foi implementado um servidor e um cliente OpenVPN, certificados por uma % autoridade central (CA) que em si é \textit{self-signed}. Para além disto, foi implementado % um sistema de autenticação de dois factores através do plugin % \textit{google-authenticator} para o OpenVPN e para o servidor de Apache. Decidimos utilizar apenas três máquinas virtuais: o cliente (ou \textit{road warrior}), a \textit{gateway} que utiliza OpenVPN e um servidor interno com OpenSSL e Apache. Isto simplifica a elaboração do projecto, mas por razões de segurança poderia querer separar a máquina de OpenSSL de outras máquinas destinadas a serviços da rede intera, pois esta contém o \textit{certificate authority} CA. % Ambos o OpenVPN eo servidor Apache utilizam 2FA, % recebendo o utilizador, e uma password que é uma concatenação da palavra-passe do utilizador % e de uma password temporária (TOTP) de 6 dígitos. O servidor de Apache implementa a mesma autenticação. \begin{tabular}{l l l} {\bf Nome} & {\bf Script} & {\bf Rede} \\\toprule Road Warrior & VM\_ROAD\_WARRIOR.sh & Rede Externa 193.168.0.0/24 \\ VPN Gateway & VM\_OPENVPN\_GATEWAY.sh & Router \\ OpenSSL / Apache & VM\_OPENSSL\_APACHE.sh & Rede Interna 10.60.0.0/24 \\ \end{tabular} \section{Preparação Inicial} \subsection{Criação de Certificados} Os certificados utilizados foram auto-certificados por uma autoridade central que ``pertence'' à máquina de OpenSSL. Esta mesma faz a gestão da lista de revogação. Todas as chaves foram criadas no mesmo computador, com as variáveis que estão neste código, aspetos importantes para mais tarde serão os parâmetros de CN que precisam de ser passados mais tarde para aceder ao Apache e ao gateway. Numa situação normal teríamos uma autoridade de certificação para enviar e no fundo gerir todos, mas para este cenário podemos inicializar as máquinas com as chaves, requests e certificados necessários. O código para gerar os certificados X.509: \begin{codeblock}[bash]{create\_all\_keys.sh} cert_ca="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=CoimbraVPN" cert_vpn="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=gateway" cert_user="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=warrior" cert_apache="/C=PT/ST=Coimbra/L=Coimbra/O=UC/CN=apache.coimbra" openssl genrsa -out "ca.key" 2048 openssl req -x509 -nodes -days 365 -key "ca.key" -out "ca.crt" -subj "$cert_ca" openssl genrsa -out "vpn.key" 2048 openssl req -new -key "vpn.key" -out "vpn.csr" -subj "$cert_vpn" openssl ca -batch -in "vpn.csr" -cert "ca.crt" -keyfile "ca.key" -out "vpn.crt" -config cheese.cfg openssl dhparam -out "dh2048.pem" 2048 openvpn --genkey secret "ta.key" openssl genrsa -out user.key openssl req -new -key user.key -out user.csr -subj "$cert_user" openssl ca -batch -in "user.csr" -cert "ca.crt" -keyfile "ca.key" -out "user.crt" -config cheese.cfg openssl genrsa -out apache.key openssl req -new -key apache.key -out apache.csr -subj "$cert_apache" -addext "subjectAltName = IP:10.60.0.1,DNS:apache" openssl ca -batch -in "apache.csr" -cert "ca.crt" -keyfile "ca.key" -out "apache.crt" -config cheese.cfg openssl --genkey secret ta.key \end{codeblock} \section{Configuração geral} Para configurar as VMs era preciso introduzir os mesmos comandos várias vezes, o que levava muitas vezes a erros de escrita, ou a correr o mesmo comando várias vezes, por isso criamos vários ficheiros .sh para conseguir facilitar o processo. A utilização de ficheiros .sh também vem com outros positivos pois facilita a testagem, e a recriação do cenário rapidamente. No entanto para os serviços que configuramos, instalar, desativar e dar flush às iptables não foi suficiente, tivemos que criar pastas e sincronizar os relógios de todas as VMs visto que elas estarem ligeiramente atrasadas nunca conseguíamos acertar na password do google-authenticator que utiliza o tempo local para calcular a sua chave. \begin{codeblock}[bash]{VM\_CONFIG.sh} yum install -y epel-release yum install -y openvpn iptables-services dhcp-client systemctl stop firewalld systemctl disable firewalld systemctl mask firewalld systemctl enable iptables iptables -F CA_DIR="/etc/pki/CA" mkdir -p "${CA_DIR}/newcerts" mkdir -p "${CA_DIR}/private" touch "${CA_DIR}/index.txt" cp ca/serial "${CA_DIR}/serial" mkdir -p /etc/openvpn/server mkdir -p /etc/openvpn/client # NOTE(vasco): tive problemas com a sincronizacao de tempo # se nao tiver sincronizado, o TOTP nao funciona systemctl stop chronyd ntpdate pool.ntp.org systemctl start chronyd \end{codeblock} \subsection{Configurar TOTP} Foi criado o ficheiro \texttt{totp} com a configuração de autenticação a ser utilizada pelo plugin de PAM para o openvpn. \begin{codeblock}{/etc/pam.d/totp} plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so totp \end{codeblock} Adicionalmente, devido às restrições de segurança do \textit{systemd}, foi necessário desativar o \texttt{ProtectHome} no serviço do OpenVPN para que o plugin PAM consiga ler os ficheiros de segredo do Google Authenticator localizados nas diretorias \textit{home} dos utilizadores. \begin{codeblock}{override.conf} [Service] ProtectHome=false \end{codeblock} Primeiro, na gateway, entramos como o utilizador desejado e obtemos a chave do gerador de palavras passes temporárias. Ao inserir a chave no \texttt{google authenticator} podemos obter um código QR, a nossa primeira chave de 6 dígitos. \begin{figure}[h] \centering \includegraphics[width=8em]{google-authenticator} \end{figure} \begin{codeblock}[bash]{} su john google-authenticator \end{codeblock} \subsection{Encaminhamento e Firewall} Para que a gateway funcione como router entre a rede externa e a rede interna, foi necessário ativar o \textit{IP forwarding} no kernel e configurar as regras de \textit{iptables} para permitir o tráfego da VPN e realizar o mascaramento de IP (NAT). % NOTA(vasco): Não temos regras de DROP a packets % talvez deviamos mudar isso nao sei <- não diz nada no enunciado ¯\_(ツ)_/¯ % também o trabalho não é sobre ip tables por isso it does make sense não fazer drop %e utilizar as regras apenas para encaminhar corretamente. % Colocar isso na conclusão tho \begin{codeblock}[bash]{firewall.sh} # Ativar encaminhamento echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf sysctl -p /etc/sysctl.conf # Regras de Firewall iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT iptables -I FORWARD 1 -i tun0 -o enp0s9 -j ACCEPT iptables -I FORWARD 1 -i enp0s9 -o tun0 -j ACCEPT iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o enp0s8 -j MASQUERADE \end{codeblock} \section{Configuração do Cliente (Road Warrior)} O cliente encontra-se na rede externa (\texttt{193.136.212.10}) e liga-se à VPN gateway na porta 1194. Para garantir a segurança, utilizamos autenticação mútua (os certificados X.509) e um \textit{two factor authentication} (2FA) como palavras-passe temporárias, geradas através do \textit{Google Authenticator}. \begin{codeblock}{client.conf} client dev tun proto udp remote 193.136.212.1 1194 ca ca.crt cert user.crt key user.key auth-user-pass cipher AES-256-GCM auth SHA256 \end{codeblock} \section{Servidor Apache e OCSP} O servidor interno (\texttt{10.60.0.1}) alberga o serviço Apache e o responder OCSP da autoridade de certificação. \subsection{Revocation e OCSP} \begin{enumerate} \item Estabelecer a ligação VPN e verificar a conectividade à rede interna. \item No diretório da autoridade de certificação (máquina \textit{host}), revogar o certificado do utilizador: \begin{codeblock}[bash]{revoke.sh} openssl ca -revoke user.crt -config cheese.cfg -keyfile ca.key -cert ca.crt \end{codeblock} \item Atualizar o ficheiro \texttt{index.txt} no servidor OCSP e reiniciar o serviço para carregar o novo estado de revogação. \item Tentar estabelecer uma nova ligação VPN e verificar que a autenticação falha devido à resposta \texttt{revoked} do responder OCSP. \end{enumerate} \subsection{Testes} Podemos validar que o OCSP \section{Conclusão} % Conclusão!!!! Atingimos o objetivo deste trabalho, conseguimos configurar o VPN tunnel, o two-factor authentication e conseguimos criar e retirar acesso aos certificados que emitimos. Utilizar mais maquinas para simular um cenario maior seria redundante, teriamos que emitir mais certificados mas não iamos aprender muito mais. Se fossemos aplicar o que fizemos no trabalho anterior podiamos dar DROP aos pacotes que não nos interessa nesta cenario, e implementar suricata para identificar possiveis ataques nos serviços. %È estranho que para uma cadeira de cybersegurança nós implementamos %pouca you know segurança. % Para aprofundar (???) yeah \end{document}