#!/bin/bash # ########################################################################### # # Nome : # Descricao : Configura uma interface e rotas para Ipsec / Strongswan # Author : Jose Edson Moreno Jr. # Email : edson.moreno@gmail.com # Versao : 0.13 # Data : 29/11/2025 # copyright : (C) 2025 by Edson Moreno # Parametros : prog # Retorno : # # CHANGELOG : # 20251129 - Acrescentado possibilidade de grupos de rotas, para grupos diferente # 20250509 - Remocao de rota default do ipsec # 20250718 - Melhorado retorno de msg ############################################################################ SRVROTAS="10.16.144.36" IPSEC_IF="ipsec0" DEFAULT_IF=${PLUTO_INTERFACE} IPSEC_LOCAL="${PLUTO_ME}" IPSEC_REMOTE="${PLUTO_PEER}" IPSEC_ADDR="${PLUTO_MY_SOURCEIP}" IPSEC_ROUTE="${PLUTO_PEER_CLIENT}" IPSEC_ROUTE="10.16.144.0/24" IPSEC_PEER="" # Pode ajustar conforme sua infra DNS_FILE="/etc/ipsec.d/resolv.conf_save" IPSEC_TABLE_ID="220" IPSEC_TABLE_NAME="ipsec" IPSEC_TABLE="${IPSEC_TABLE_NAME}" RT_TABLES_DIR="/etc/iproute2" RT_TABLES_FILE="${RT_TABLES_DIR}/rt_tables" LOG="/var/log/ipsec-updown.log" echo "===== UPDOWN $(date) =====" >> $LOG env >> $LOG function ensure_iproute2_table(){ # Mantém o comportamento antigo nas versões que já possuem a tabela nomeada. # O ID numérico 220 é fallback para Ubuntu 26 quando /etc/iproute2/rt_tables # não existe ou ainda não possui o alias "ipsec". if [ -f "${RT_TABLES_FILE}" ] && grep -Eq "^[[:space:]]*[0-9]+[[:space:]]+${IPSEC_TABLE_NAME}([[:space:]]|$)" "${RT_TABLES_FILE}"; then IPSEC_TABLE="${IPSEC_TABLE_NAME}" return 0 fi IPSEC_TABLE="${IPSEC_TABLE_ID}" if [ ! -d "${RT_TABLES_DIR}" ]; then mkdir -p "${RT_TABLES_DIR}" 2>/dev/null || return 0 fi if [ ! -f "${RT_TABLES_FILE}" ]; then { echo "#" echo "# reserved values" echo "#" echo "255 local" echo "254 main" echo "253 default" echo "0 unspec" echo "#" echo "# local" echo "#" } > "${RT_TABLES_FILE}" 2>/dev/null || return 0 fi if ! grep -Eq "^[[:space:]]*${IPSEC_TABLE_ID}[[:space:]]+${IPSEC_TABLE_NAME}([[:space:]]|$)" "${RT_TABLES_FILE}" \ && ! grep -Eq "^[[:space:]]*[0-9]+[[:space:]]+${IPSEC_TABLE_NAME}([[:space:]]|$)" "${RT_TABLES_FILE}" \ && ! grep -Eq "^[[:space:]]*${IPSEC_TABLE_ID}[[:space:]]+" "${RT_TABLES_FILE}"; then echo "${IPSEC_TABLE_ID} ${IPSEC_TABLE_NAME}" >> "${RT_TABLES_FILE}" 2>/dev/null || true fi if [ -f "${RT_TABLES_FILE}" ] && grep -Eq "^[[:space:]]*[0-9]+[[:space:]]+${IPSEC_TABLE_NAME}([[:space:]]|$)" "${RT_TABLES_FILE}"; then IPSEC_TABLE="${IPSEC_TABLE_NAME}" fi } function start(){ # Salvando DNS if [ "$(systemctl is-active systemd-resolved)" == "active" ]; then resolvectl dns ${DEFAULT_IF} | awk -F': ' '{gsub(" ","\n",$2)}{print $2}' | awk '{print "nameserver " $1}' > ${DNS_FILE} resolvectl domain ${DEFAULT_IF} | awk -F': ' '{print "search " $2}' >> ${DNS_FILE} else cp -f /etc/resolv.conf ${DNS_FILE} fi # Cria a interface se não existir echo -en "Criando interface ${IPSEC_IF}" ip link show ${IPSEC_IF} >/dev/null 2>&1 if [ $? -ne 0 ]; then ip link add ${IPSEC_IF} type dummy fi ip link set ${IPSEC_IF} up mtu 1400 echo " - OK ✅" # Atribui IP na IPSEC echo "Atribui IP na IPSEC ${IPSEC_IF}" ip addr flush dev ${IPSEC_IF} ip addr add "${IPSEC_ADDR}/32" dev ${IPSEC_IF} # Tabela IPSEC echo -en "Preparando tabela de rotas IPSEC" ensure_iproute2_table ip route flush table ${IPSEC_TABLE} if [ $? -ne 0 ]; then echo " - Falha ❌" else echo " - OK ✅" fi echo -en "Acrescentando rota ${IPSEC_ROUTE} na interface ${IPSEC_IF}" ip route add ${IPSEC_ROUTE} dev ${IPSEC_IF} table ${IPSEC_TABLE} if [ $? -ne 0 ]; then echo " - Falha ❌" else echo " - OK ✅" fi echo -en "Criando Regras para interface ${IPSEC_IF}" ret=0 ip rule add from ${IPSEC_ADDR} lookup ${IPSEC_TABLE} ret=$((ret + $?)) ip rule add to ${IPSEC_ADDR} lookup ${IPSEC_TABLE} ret=$((ret + $?)) ip rule add to ${IPSEC_REMOTE} lookup main ret=$((ret + $?)) if [ ${ret} -ne 0 ]; then echo " - Falha ❌" else echo " - OK ✅" fi # ip route add default dev ${IPSEC_IF} table ${IPSEC_TABLE} metric 11 # Remove o IP da interface errada (wlo1 ou default) echo -en "Removendo ${IPSEC_ADDR}/32 da interface ${DEFAULT_IF}" ip addr del "${IPSEC_ADDR}/32" dev "${DEFAULT_IF}" 2>/dev/null if [ $? -ne 0 ]; then echo " - Falha ❌" else echo " - OK ✅" fi # sysctl safe defaults echo 0 > /proc/sys/net/ipv4/conf/${IPSEC_IF}/rp_filter echo 1 > /proc/sys/net/ipv4/conf/${IPSEC_IF}/accept_local tentativa=1 while [ 1 ];do echo -en "Procurando ${IPSEC_IF} - " ip a | grep ${IPSEC_IF} > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "OK ✅" break fi echo "Tentativa ${tentativa} ❌" tentativa=$((tentativa + 1)) if [ $tentativa -gt 5 ]; then echo "Erro: Excesso tentativas ❌" exit 2 fi sleep 2 done nc -z -w3 "${SRVROTAS}" "443" >/dev/null 2>&1 if [ $? -eq 0 ]; then echo "Servidor de rotas ${SRVROTAS} OK ✅" else echo "Servidor de rotas ${SRVROTAS} não está respondendo na porta 443 - ❌" exit 2 fi if [ -z ${PLUTO_MY_ID} ]; then unset grupo_vpn unset msg_grp else grupo_vpn="_${PLUTO_MY_ID}" msg_grp="de ${PLUTO_MY_ID}" fi echo -en "Acrescentado rotas extras ${msg_grp:-} em ${IPSEC_TABLE} " nroute=0 nroute_err=0 for ROUTE_IPSEC in $(wget -q --no-check-certificate https://${SRVROTAS}/Ipsec_Routes${grupo_vpnx:-} -O- ); do ip route add ${ROUTE_IPSEC} dev ${IPSEC_IF} table ${IPSEC_TABLE} >/dev/null 2>&1 if [ $? -eq 0 ]; then nroute=$((nroute + 1)) else nroute_err=$((nroute_err + 1)) fi done echo "- Finalizado com sucesso o acrescimo de ${nroute} rotas, e ${nroute_err} com falha - OK ✅" ip route show | egrep "default .* dev ${IPSEC_IF}" > /dev/null if [ $? -eq 0 ]; then echo -en "Removendo rota default de dev ${IPSEC_IF} em table ${IPSEC_TABLE}" ip route del default dev ${IPSEC_IF} table ${IPSEC_TABLE} > /dev/null 2>&1 if [ $? -ne 0 ]; then echo " - Falha ❌" else echo " - OK ✅" fi fi ip route show table ${IPSEC_TABLE} | grep -i default > /dev/null 2>&1 if [ $? -eq 0 ]; then echo -en "Removendo rota default da tabela ${IPSEC_TABLE}" ip route del $(ip route show table ${IPSEC_TABLE} | grep default ) table ${IPSEC_TABLE} >/dev/null 2>&1 if [ $? -ne 0 ]; then echo " - Falha ❌" else echo " - OK ✅" fi fi if [ "$(systemctl is-active systemd-resolved)" == "active" ]; then IPDNS=$(wget -q --no-check-certificate https://${SRVROTAS}/Ipsec_DNS -O- | grep nameserver | awk '{printf $2" "}') resolvectl dns ${IPSEC_IF} ${IPDNS} SEARCHDNS=$(wget -q --no-check-certificate https://${SRVROTAS}/Ipsec_DNS -O- | grep search | awk '{gsub("search","",$0)}{printf $0}') resolvectl domain ${IPSEC_IF} ${SEARCHDNS} echo "Configurado resolvectl dns com DNS Server: ${IPDNS} - OK ✅" else wget -q --no-check-certificate https://${SRVROTAS}/Ipsec_DNS -O- > /etc/resolv.conf echo "Configurado /etc/resolv.conf - OK ✅" fi echo ">>> IPSEC ${IPSEC_IF} configurada com ${PLUTO_MY_SOURCEIP}/32 para ${PLUTO_PEER_CLIENT}" } function stop(){ ip rule del from ${IPSEC_ADDR} lookup ${IPSEC_TABLE} 2>/dev/null ip rule del to ${IPSEC_ADDR} lookup ${IPSEC_TABLE} 2>/dev/null ip route flush table ${IPSEC_TABLE} #ip route del local ${IPSEC_ADDR} dev lo 2>/dev/null ip link set ${IPSEC_IF} down ip link del ${IPSEC_IF} 2>/dev/null if [ "$(systemctl is-active systemd-resolved)" == "active" ]; then IPDNS=$(grep nameserver ${DNS_FILE}| awk '{printf $2" "}') resolvectl dns ${IPSEC_IF} ${IPDNS} SEARCHDNS=$(grep search ${DNS_FILE} | awk '{printf $2" "}') resolvectl domain ${IPSEC_IF} ${SEARCHDNS} else cp -f ${DNS_FILE} /etc/resolv.conf fi echo ">>> Interface ${IPSEC_IF} removida" } case "${PLUTO_VERB}" in up-client) start >> ${LOG} 2>&1 ;; down-client) stop >> ${LOG} 2>&1 ;; esac exit 0