sexta-feira, 20 de março de 2020
Configurando VPN IPsec site-to-site FreeBSD
Recentemente tive que fazer uma VPN site-to-site na empresa onde trabalho, normalmente o pessoal acaba utilizando Linux pra isso, mas para essa empreitada decidi utilizar o FreeBSD, que tem uma vantagem ao meu ver que é, poder atualizar de uma versão major para outra sem necessidade de formatação, à já conhecida estabilidade do seu SO e também por possuir o PF como firewall para filtro de pacotes. Como não há praticamente "how-to" desse tipo de coisa na internet, foi um trabalho hercúleo de ser feito, mas vou deixar registrado aqui como proceder, assim ajudando mais pessoas na configuração de VPN's do tipo IPsec.
O FreeBSD tem como missão a estabilidade, ou seja, serviços de rotas de VPN, integração com filtro de pacotes e afins no kernel, não existem, justamente para preservar o kernel de possíveis instabilidades.
Dito isso, vamos a configuração de fato:
OBS: Esse tutorial parte do pressuposto que você já tenha um FreeBSD instalado e com internet para download de pacotes e configuração do túnel.
1 - A primeira coisa à ser feita é ativar no arquivo "/etc/rc.conf" o firewall PF para filtragem de pacotes, devemos inserir as seguintes linhas no arquivo:
#Habilita FW
pf_enable="YES" ## habilita o PF no boot do sistema
pf_rules="/etc/pf.conf" ## arquivo onde as regras serão inseridas
pflog_enable="YES" ## habilita o PF para logar o tráfego passante
pflog_logfile="/var/log/pflog" ## arquivo de log do PF
2 - Depois devemos ativar a interface de encapsulamento do túnel IPsec no kernel, por padrão isso não vem ativo. Insira a seguinte linha no arquivo "/boot/loader.conf"
if_enc_load="YES"
Devemos também ativar essas flags sugeridas no arquivo "/etc/sysctl.conf", conforme sugerido na man da interface:
net.enc.out.ipsec_bpf_mask=1
net.enc.out.ipsec_filter_mask=1
net.enc.in.ipsec_bpf_mask=2
net.enc.in.ipsec_filter_mask=2
Os valores acima são inseridos para que o tráfego seja filtrado pelo firewall
Man da interface: https://www.freebsd.org/cgi/man.cgi?query=enc&sektion=4&manpath=freebsd-release-ports
Também devemos inserir no arquivo "/etc/rc.conf" a linha para inicialização da interface enc0
ifconfig_enc0="up"
Após executar as configurações acima, vamos efetuar o reboot da máquina.
3 - Depois de rebootar a máquina, agora com a interface enc0 e o PF já ativo, vamos instalar o pacote strongswan para configuração do túnel da VPN:
# pkg install strongswan
Depois devemos ativar o strongswan no boot do sistema com o comando abaixo:
# sysrc strongswan=YES
Com o comando acima, é inserida uma linha no arquivo "/etc/rc.conf" para inicialização do serviço junto ao sistema
4 - Agora vamos configurar o nosso túnel no arquivo de configuração "/usr/local/etc/ipsec.conf"
# ipsec.conf - strongSwan IPsec configuration file
config setup
charondebug="all"
uniqueids=yes
strictcrlpolicy=no
conn %default
conn site1-site2 # nome da conexao
auto=route # parametro que informa ao strongswan, que ele é roteado via PF
left=1.1.1.1 # IP válido do nosso lado do tunel
leftsubnet=10.10.0.0/24 #Rede inválida da LAN do nosso lado
ike=aes256-sha2_256-modp1024! # Criptografia de fase 1 do túnel
esp=aes256-sha2_256-modp1024! # Criptografia de fase 2 do túnel
ikelifetime=1h #Tempo de expiração para renegociação das chaves
lifetime=24h # Quanto tempo a conexão deve durar desde a conexão até a expiração
keyexchange=ikev2 # Tipo de chave de troca de conexão
authby=secret # Método de autenticação
type=tunnel # Tipo de conexão, por padrão é túnel
right=2.2.2.2 # IP válido do outro lado do túnel
rightsubnet=10.10.10.0/24 # Rede inválida do outro lado do túnel
5 - Outra coisa que devemos fazer é trocar a configuração dentro do arquivo "/usr/local/etc/strongswan.conf" na opção "install_routes" de "yes" para "no" conforme segue:
# strongswan.conf - strongSwan configuration file
#
# Refer to the strongswan.conf(5) manpage for details
#
# Configuration changes should be made in the included files
charon {
install_routes = no
load_modular = yes
plugins {
include strongswan.d/charon/*.conf
}
}
Caso essa opção se mantenha ativa, gera uma tabela de rotas paralelas, o que nos meus testes não se mostrou muito recomendado, porque quando fica no valor default ele gera uma rota do site2 apontando para o IP válido da interface externa. No meu caso que o roteador à frente era BSD, o pacote saia com source de ip inválido tentando sair pra internet, gerando descarte do pacote.
6 - Feita a configuração acima, devemos inserir a chave de negociação do túnel no arquivo "/usr/local/etc/ipsec.secrets", conforme exemplo:
# ipsec.secrets - strongSwan IPsec secrets file
1.1.1.1 2.2.2.2 : PSK IE7ChwWERTIW123@#$
Lembrando que a chave deve ser a mesma nos dois lados e a chave é gerada pelo administrador.
7 - Após isso, podemos já subir o túnel através do comando:
# service ipsec start
E para vermos se o túnel está ok, executamos o comando:
# ipsec status
# ipsec status
Routed Connections:
site1-to-site2{1}: ROUTED, TUNNEL, reqid 1
site1-to-site2{1}: 10.10.0.0/24 === 10.10.10.0/24
Security Associations (1 up, 0 connecting):
site1-to-site2[31]: ESTABLISHED 10 minutes ago, 1.1.1.1[1.1.1.1]...2.2.2.2[2.2.2.2]
site1-to-site2{32}: INSTALLED, TUNNEL, reqid 1, ESP SPIs: c9896268_i 0926547e_o
site1-to-site2{32}: 10.10.0.0/24 === 10.10.10.0/24
7 - Para que o túnel funcione corretamente, devemos agora sim, inserir uma rota manualmente para o nosso túnel strongswan, conforme segue:
- Inserção via terminal
# route add -net 10.10.10.0/24 10.10.0.1 #Primeiro campo de IP rota do site2 e o segundo IP é nosso servidor
Para haver resiliência do servidor, devemos inserir as rotas no arquivo "/etc/rc.local", como uma rota estática da interface de LAN do nosso equipamento conforme segue:
ifconfig_xn0="inet 10.10.0.1 netmask 255.255.255.0"
static_routes="ipsec"
route_ipsec="-net 10.10.10.0/24 10.10.0.1"
8 - Para que seja possível rotear os pacotes através do túnel e ocorrer comunicação entre as redes devemos ativar a flag de encaminhamento do kernel no arquivo "/etc/sysctl" conforme segue:
net.inet.ip.forwarding=1
Para já conseguirmos rotear sem reiniciar o servidor, devemos executar o comando:
# sysctl -p /etc/sysctl.conf
Após efetuar os passo acima, a VPN entre as redes já estará UP e totalmente funcional.
Agora vem a segunda parte dessa missão, que é onde o meu cenário se encaixa.
Digamos que seu FreeBSD tenha mais redes atrás da LAN que não a diretamente conectada e tais redes também necessitem comunicar com as máquinas do outro lado do túnel IPsec, abaixo descrevo como proceder nesses casos:
1 - Devemos primeiro inserir no PF uma regra de src-nat(no Linux postrouting) para que as requisições para a rede do site2 saiam com o IP da rede local do tunel VPN. Devemos inserir a seguinte regra no arquivo do nosso firewall que está em "/etc/pf.conf"
#src-nat para acesso da nossa rede com o IP do servidor de VPN
nat on enc0 from 10.10.0.0/16 to 10.10.10.0/24 -> 10.10.0.1
2 - Agora vem o pulo do gato, que mais me custou tempo na configuração disso tudo, quando você sobe o túnel, são criadas rotas no kernel que ficam dentro de uma base de dados de rotas do IPsec que não são visíveis via comando ipsec, para visualizarmos as rotas já inseridas, executamos o seguinte comando:
#setkey -DP
10.10.10.0/24[any] 10.10.0.0/24[any] any
in ipsec
esp/tunnel/1.1.1.1-2.2.2.2/unique:1
created: Mar 19 16:58:11 2020 lastused: Mar 19 16:58:11 2020
lifetime: 9223372036854775807(s) validtime: 0(s)
spid=5 seq=2 pid=10314 scope=global
refcnt=1
10.10.0.0/24[any] 10.10.10.0/24[any] any
out ipsec
esp/tunnel/1.1.1.1-2.2.2.2/unique:1
created: Mar 19 16:58:11 2020 lastused: Mar 19 16:58:11 2020
lifetime: 9223372036854775807(s) validtime: 0(s)
spid=6 seq=0 pid=10314 scope=global
refcnt=1
Você pode se perguntar, porque não inseriu só no campo "left" do tunel o /16 e segue o jogo, certo? Pois é, é viável, mas o /16 sobrepõe a rede do nosso site2, que no caso em questão é uma rede que não está sob minha gerência, logo não posso trocar pra outro range.
3 - Para fazermos isso dentro da tabela de roteamento do ipsec, devemos ativar um arquivo de rotas no "/etc/rc.conf", da seguinte forma:
ipsec_enable="YES" # Configura como sim, para rodar o setkey no arquivo ipsec_file
ipsec_file="/etc/ipsec.conf" # Nome do arquivo onde será inserido o setkey
4 - Após isso, vamos inserir as linhas no arquivo para que dentro da tabela de rotas do ipsec, comporte nosso /16 e o nat seja executado com sucesso.
As regras abaixo devem ser inseridas no arquivo "/etc/ipsec.conf"
#ipsec out
spdadd -4 10.10.0.0/16 10.10.10.0/24 any -P out ipsec esp/tunnel/1.1.1.1-2.2.2.2/unique:1;
#ipsec in
spdadd -4 10.10.10.0/24 10.10.0.0/16 any -P in ipsec esp/tunnel/1.1.1.1-2.2.2.2/unique:1;
OBS: O número 1 ao lado do unique, é o número de identificação do túnel na tabela de rotas.
5 - Após isso feito, depois de reiniciarmos o serviço do strongswan, a tabela de rotas ipsec ficará dessa forma:
root@vpn-ipsec:~ # setkey -DP
10.10.10.0/24[any] 10.10.0.0/16[any] any
in ipsec
esp/tunnel/1.1.1.1-2.2.2.2/unique:1
spid=2 seq=3 pid=21756 scope=global
refcnt=1
10.10.10.0/24[any] 10.10.0.0/24[any] any
in ipsec
esp/tunnel/1.1.1.1-2.2.2.2/unique:1
created: Mar 20 10:20:01 2020 lastused: Mar 20 10:20:01 2020
lifetime: 9223372036854775807(s) validtime: 0(s)
spid=5 seq=2 pid=21756 scope=global
refcnt=1
10.10.0.0/16[any] 10.10.10.0/24[any] any
out ipsec
esp/tunnel/1.1.1.1-2.2.2.2/unique:1
spid=1 seq=1 pid=21756 scope=global
refcnt=1
10.10.0.0/24[any] 10.10.10.10.0/24[any] any
out ipsec
esp/tunnel/1.1.1.1-2.2.2.2/unique:1
created: Mar 20 10:20:01 2020 lastused: Mar 20 10:20:01 2020
lifetime: 9223372036854775807(s) validtime: 0(s)
spid=6 seq=0 pid=21756 scope=global
refcnt=1
Após esses passos, é possível conectar via tunel IPsec com nat de outras redes.
Alguns link's que me foram úteis nessa empreitada:
Setkey https://www.freebsd.org/cgi/man.cgi?query=setkey&sektion=8&manpath=freebsd-release-ports
Enc0: https://www.freebsd.org/cgi/man.cgi?query=enc&sektion=4&manpath=freebsd-release-ports
PF: https://www.freebsd.org/cgi/man.cgi?pf(4)
Strongswan: https://www.freebsd.org/cgi/man.cgi?query=%20strongswan.conf&manpath=FreeBSD+Ports+9.2-RELEASE
Ipsec: https://www.freebsd.org/cgi/man.cgi?query=ipsec.conf
Tabela de rotas: https://www.freebsd.org/cgi/man.cgi?route
Por hoje é só have a nice day =D
Assinar:
Postar comentários (Atom)
Nenhum comentário:
Postar um comentário