Tokens A3 e Linux

ATENÇÃO: ESTE SCRIPT FOI GENERALIZADO E ESTÁ DISPONÍVEL NO GITHUB!

Ainda não existe uma maneira de utilizar tokens A3 (que talvez seja visto por aí como etoken USB) em Linux usando NetworkManager e as ferramentas gráficas dos ambientes desktop. Por isso, é necessário um checklist para fazer funcionar em uma distro Linux.

Passo 1: configurar o token A3.

É trabalhoso, mas basta seguir os passos se seu token for o ePass2003 ou se seu token for o StarSign G+D. Ambos são para Ubuntu 20.04, mas não deve ter grandes diferenças para o Ubuntu 22.04.

Passo 2: configurar o script de conexão.

Como não existe como conectar via GUI, temos que conectar via script. Um exemplo de script está listado abaixo:

#!/bin/bash
#
# Script de conexão e desconexão à VPN com token A3
#
# 

prog_name=$(basename $0)

# 
# Definimos as variáveis que utilizaremos em caso de conexão
# TODAS as modificações de personalização do script são feitas aqui
#

#
# Variáveis básicas
#
USERCERT="certificado-do-usuario"
SERVERCERT="certificado-do-servidor"
CAFILE="/local/da/cadeia/do/token/a3.pem"
PORTAL="portal.da.vpn.empresa.com.br"
USUARIO="login@empresa.com.br"

#
# Algumas VPNs permitem ao utilizador escolher o authgroup de conexão (mais próximo geograficamente etc)
# Descomente e modifique a variável GATEWAY para o authgroup desejado
#
#GATEWAY="GW_ESPECIFICO"

#
# Estas variáveis não são necessárias caso a conexão VPN sete automaticamente os DNS
# Caso sejam necessários mais de um DNS ou domínio, crie outras variáveis (DNS2, DOMAIN2 etc)
#
DNS1=dns.interno.da.vpn
DOMAIN1="~dominio.interno.da.vpn"

#
# FIM das modificações de personalização do script
#

#
# PID de execução
#
PID=/run/vpn.pid

#
# Ajuda
#
function help {
	echo "Uso: $prog_name [-c] [-d]"
	echo
	echo "Opções"
	echo "    -c, --connect              Conecta na VPN. Precisa ter o token A3 plugado na porta USB"
	echo "    -d, --disconnect           Desconecta a VPN caso esteja rodando"
	echo
}

function check_root {
	#
	# Checando se estamos rodando como root
	#
	echo "Checando se estamos rodando como root..."
	if [[ $(id -u) -ne 0 ]]
	then
  		echo "Este script precisa rodar como root!"
 		echo "Use o comando \"sudo\" para executar este script."
 		exit 1
	fi
}

function connect {
	check_root
	#
	# Testa se o token está plugado na USB
	# Se o token não estiver plugado na USB, avisa e sai sem conectar
	#
	echo
	echo "Checando se o token está plugado em uma porta USB..."
	TEM_TOKEN=$(p11tool --list-tokens | grep "Token" | wc -l)
	if [[ $TEM_TOKEN -eq 1 ]]
	then
		echo "Não consegui encontrar um token!"
		exit 1
	fi

	#
	# Se tiver plugado, conecta com o Openconnect
	# O utilizador é alertado que precisa do PIN do token *e* da senha
	#
	echo "*** ATENÇÃO ***"
	echo "Entre com o PIN do token e a senha quando solicitado."
	openconnect --certificate $USERCERT --servercert $SERVERCERT --protocol=gp --cafile=$CAFILE --disable-ipv6 --syslog --pid-file=$PID --background $PORTAL --user $USUARIO
	#
	# Caso $GATEWAY seja necessário, adicione '--authgroup $GATEWAY' na linha de conexão do openconnect 

    #
    # Já que a saída está toda no syslog, precisamos checar se *realmente* estamos conectados.
    # Para isso, precisamos esperar a VPN estabilizar (ou não)
    #
    echo "Esperando a VPN estabilizar... Aguarde!"
    sleep 30 
    ENDIP=$(ip a show dev tun0 2>/dev/null | grep -w "inet" | cut -d " " -f 6 | cut -d "/" -f 1)
    if [[ -z $ENDIP ]]
    then
            echo "Não consegui identificar um endereço IP! Verifique se estamos logados na VPN."
            exit 1
    else
            echo "Estamos conectados à VPN com o IP "$ENDIP
    fi

	#
	# Pelo menos no Ubuntu 20.04, o openconnect não está configurando automaticamente os DNS e os domínios de search para a conexão da VPN
	# Por isso, as linhas abaixo são necessárias
	#
	# Dica retirada de https://www.gabriel.urdhr.fr/2020/03/17/systemd-revolved-dns-configuration-for-vpn/
	#
	resolvectl dns tun0 $DNS1
	resolvectl domain tun0 $DOMAIN1
}

function disconnect {
	check_root
	#
	# Checando para saber se a VPN está rodando pelo arquivo PID
	#
	echo
	echo "Checando se a VPN está realmente conectada..."
	if [[ ! -f $PID ]]
	then
		echo "Não encontrei o arquivo de PID da VPN. A VPN está ligada?"
		exit 1
	fi
	#
	# Se estiver rodando, fecha a conexão com um SIGINT para o processo
	#
	echo
	echo "Encerrando a VPN"
	PIDNUM=$(cat $PID)
	kill -SIGINT $PIDNUM
	sleep 10
	echo "Desconectados!"
}

#
# Laço principal
#
subcommand=$1

#
# Limpa a tela e apresenta um banner
#
clear
echo "     SCRIPT DE CONTROLE DE CONEXÃO À VPN USANDO TOKEN A3"
echo

#
# Executa os subcomandos ou devolve com erro ou ajuda
#
case $subcommand in
	"" | "-h" | "--help")
	help
	;;
	"-c" | "--connect")
	connect
	;;
	"-d" | "--disconnect")
	disconnect
	;;
	*)
	echo "Erro: '$subcommand' não é um subcomando conhecido." >&2
	echo "       Execute '$prog_name --help' para ajuda dos subcomandos." >&2
	exit 1
	;;
esac

Uma sugestão é salvar o script, com as modificações necessárias para a sua VPN, com o nome vpn, torná-lo executável e copiá-lo para um diretório no $PATH, p.ex. /usr/local/bin.

Passo 3: conexão e desconexão.

Para conectar à VPN:

$ sudo vpn -c

Para deconectar da VPN:

$ sudo vpn -d

O script exige a conexão usando sudo ou como root, apesar de ser necessário apenas caso tenham que ser setadas informações de DNS e domínio interno da VPN; estas modificações ficam como exercício para o leitor interessado.


2022-09-29