relatorio: vpn gateway
This commit is contained in:
@@ -14,7 +14,10 @@
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
||||
\newpage
|
||||
\tableofcontents
|
||||
|
||||
\newpage
|
||||
|
||||
\section{Introdução}
|
||||
@@ -66,8 +69,6 @@ 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"
|
||||
@@ -90,10 +91,34 @@ openssl ca -batch -in "apache.csr" -cert "ca.crt" -keyfile "ca.key" -out "apache
|
||||
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.
|
||||
Como o CA foi criado ``\textit{in place}'', e não na sua pasta prédefinida, foi necessário utilizar
|
||||
um configuração própria para definir os ficheiros \textit{index.txt} e \textit{serial}.
|
||||
|
||||
\begin{codeblock}[bash]{cheese.cfg}
|
||||
[ ca ]
|
||||
default_ca = CA_default
|
||||
[ CA_default ]
|
||||
default_days = 365
|
||||
database = index.txt
|
||||
serial = serial
|
||||
copy_extensions = copy
|
||||
new_certs_dir = .
|
||||
default_md = sha256
|
||||
policy = policy_any
|
||||
[ policy_any ]
|
||||
commonName = supplied
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{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 visto que utiliza o tempo local para calcular a sua chave.
|
||||
|
||||
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
|
||||
@@ -119,15 +144,154 @@ ntpdate pool.ntp.org
|
||||
systemctl start chronyd
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Configurar TOTP}
|
||||
|
||||
\section{VPN Gateway}
|
||||
|
||||
\subsection{Configuração da Máquina}
|
||||
|
||||
Como já foi dito anteriormente, cada máquina vem com um \textit{script}
|
||||
que instala toda a configuração necessária.
|
||||
|
||||
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]{VM\_VPN\_GATEWAY.sh}
|
||||
#!/bin/bash
|
||||
# --- configuracao --- #
|
||||
source VM_CONFIG.sh
|
||||
yum install -y google-authenticator qrencode ntpsec
|
||||
|
||||
# --- forwarding --- #
|
||||
if_fora="enp0s8"
|
||||
ip_fora="193.136.212.1"
|
||||
if_dentro="enp0s9"
|
||||
ip_dentro="10.60.0.3"
|
||||
mega_tunel="tun0"
|
||||
ip_mega_tunel="10.8.0.0/24"
|
||||
|
||||
ifconfig $if_fora $ip_fora netmask 255.255.255.0
|
||||
ifconfig $if_dentro $ip_dentro netmask 255.255.255.0
|
||||
|
||||
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
|
||||
sysctl -p /etc/sysctl.conf
|
||||
|
||||
iptables -I INPUT 1 -p udp --dport 1194 -j ACCEPT
|
||||
iptables -I FORWARD 1 -i $mega_tunel -o $if_dentro -j ACCEPT
|
||||
iptables -I FORWARD 1 -i $if_dentro -o $mega_tunel -j ACCEPT
|
||||
iptables -I FORWARD 1 -i $mega_tunel -o $if_fora -j ACCEPT
|
||||
iptables -I FORWARD 1 -i $if_fora -m state --state ESTABLISHED,RELATED -j ACCEPT
|
||||
iptables -t nat -A POSTROUTING -s $ip_mega_tunel -o $if_fora -j MASQUERADE
|
||||
iptables-save > /etc/sysconfig/iptables
|
||||
|
||||
# --- vpn server --- #
|
||||
vpn_dir="/etc/openvpn/server"
|
||||
cp ca/ta.key $vpn_dir
|
||||
cp ca/ca.crt $vpn_dir
|
||||
cp ca/vpn.key $vpn_dir
|
||||
cp ca/vpn.crt $vpn_dir
|
||||
cp ca/dh2048.pem $vpn_dir
|
||||
cp conf/vpn.conf $vpn_dir
|
||||
cp conf/ocsp-verify.sh $vpn_dir
|
||||
cp conf/totp /etc/pam.d/
|
||||
systemctl enable --now openvpn-server@vpn.service
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Configuração do Serviço OpenVPN}
|
||||
|
||||
|
||||
O servidor OpenVPN utiliza um certificado X.509 assinado pelo nosso \textit{Certificate Authority} (CA).
|
||||
E faz uso de um script \texttt{oscp-verify.sh} para validar ou revogar os certificados através do servidor OCSP.
|
||||
|
||||
\begin{codeblock}{vpn.conf}
|
||||
local 193.136.212.1
|
||||
port 1194
|
||||
proto udp
|
||||
dev tun
|
||||
|
||||
verb 4
|
||||
|
||||
ca /etc/openvpn/server/ca.crt
|
||||
cert /etc/openvpn/server/vpn.crt
|
||||
key /etc/openvpn/server/vpn.key
|
||||
dh /etc/openvpn/server/dh2048.pem
|
||||
|
||||
topology subnet
|
||||
server 10.8.0.0 255.255.255.0
|
||||
push "route 10.60.0.0 255.255.255.0"
|
||||
|
||||
# ocsp and revocation
|
||||
script-security 2
|
||||
tls-verify /etc/openvpn/server/ocsp-verify.sh
|
||||
# auth
|
||||
cipher AES-256-GCM
|
||||
auth SHA256
|
||||
|
||||
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so totp
|
||||
tls-auth /etc/openvpn/server/ta.key 0
|
||||
\end{codeblock}
|
||||
|
||||
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
|
||||
\begin{codeblock}{totp}
|
||||
auth required pam_google_authenticator.so forward_pass
|
||||
auth required pam_unix.so use_first_pass
|
||||
account required pam_unix.so
|
||||
\end{codeblock}
|
||||
|
||||
Este script simplesmente comunica com o servidor OpenSSl
|
||||
e verifica o resultado.
|
||||
|
||||
\begin{codeblock}{ocsp\_verify.sh}
|
||||
#!/bin/bash
|
||||
depth=$1
|
||||
env >> /etc/openvpn/server/ocsp_env.log
|
||||
if [ "$depth" -eq 0 ]; then
|
||||
echo "Checking OCSP for serial=$tls_serial_0" >> /etc/openvpn/server/ocsp.log
|
||||
if [ -n "$tls_serial_0" ]; then
|
||||
# e preciso converter o serial para hexadecimal porque o openssl espera em hex
|
||||
hex_serial=$(printf '%x' "$tls_serial_0")
|
||||
status=$(openssl ocsp -issuer /etc/openvpn/server/ca.crt -serial "0x$hex_serial" -url http://10.60.0.1:8888 -CAfile /etc/openvpn/server/ca.crt 2>>/etc/openvpn/server/ocsp.log)
|
||||
echo "OCSP Status: $status" >> /etc/openvpn/server/ocsp.log
|
||||
|
||||
if echo "$status" | grep -q "revoked"; then
|
||||
echo "Result: REVOKED" >> /etc/openvpn/server/ocsp.log
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if echo "$status" | grep -q "good"; then
|
||||
echo "Result: GOOD" >> /etc/openvpn/server/ocsp.log
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Result: UNKNOWN/ERROR" >> /etc/openvpn/server/ocsp.log
|
||||
exit 1
|
||||
else
|
||||
echo "tls_serial_0 is empty!" >> /etc/openvpn/server/ocsp.log
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "ERROR: depth > 0" >> /etc/openvpn/server/ocsp.log
|
||||
|
||||
exit 0
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Erros}
|
||||
|
||||
Um dos erros que encontramos pelo caminho foi que o OpenSSL OCSP espera que o
|
||||
\textit{serial} esteja num formato diferente do que o esperado. Foi necessário
|
||||
converter para hexadecimal primeiro.
|
||||
|
||||
|
||||
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
|
||||
@@ -138,6 +302,8 @@ localizados nas diretorias \textit{home} dos utilizadores.
|
||||
ProtectHome=false
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Configurar o utilizador com TOTP}
|
||||
|
||||
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
|
||||
@@ -153,32 +319,12 @@ su john
|
||||
google-authenticator
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Encaminhamento e Firewall}
|
||||
\section{VPN Client (Road Warrior)}
|
||||
|
||||
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).
|
||||
\subsection{Configuração da Máquina}
|
||||
ads
|
||||
|
||||
% 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)}
|
||||
\subsection{Configuração do Cliente OpenVPN}
|
||||
|
||||
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)
|
||||
@@ -198,12 +344,29 @@ cipher AES-256-GCM
|
||||
auth SHA256
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Testes}
|
||||
|
||||
\section{Servidor Apache e OCSP}
|
||||
|
||||
\subsection{Configuração da Máquina}
|
||||
|
||||
asd
|
||||
|
||||
\subsection{Configuração do Serviço Apache}
|
||||
|
||||
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}
|
||||
\subsubsection{Testes}
|
||||
|
||||
1. verificar que é necessário o dominio,
|
||||
|
||||
1. verificar que é necessário o https,
|
||||
|
||||
1. verificar que é necessário o certificado,
|
||||
|
||||
|
||||
\subsection{Configuração do Serviço OpenSSL}
|
||||
|
||||
\begin{enumerate}
|
||||
\item Estabelecer a ligação VPN e verificar a conectividade à rede interna.
|
||||
@@ -215,14 +378,23 @@ openssl ca -revoke user.crt -config cheese.cfg -keyfile ca.key -cert ca.crt
|
||||
\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}
|
||||
\subsubsection{Testes}
|
||||
|
||||
Podemos validar que o OCSP
|
||||
|
||||
1. verificar que recebe os certificados e responde
|
||||
|
||||
1. verificar que revocation funciona
|
||||
|
||||
|
||||
\section{Teste Integrado}
|
||||
|
||||
verificamos coisas
|
||||
|
||||
\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
|
||||
@@ -230,6 +402,7 @@ 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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user