239 lines
9.5 KiB
TeX
239 lines
9.5 KiB
TeX
\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}
|