Nosso objetivo é prover alguns scripts que podem ser usados para funções de consulta da tabela ARP e bloqueio/desbloqueio de MACs em máquinas GNU/Linux remotas. Para executar os comandos remotamente, será usado o protocolo SSH com autenticação baseada em chaves públicas. A configuração do SSH para esse ambiente será um pouco mais complexa que o usual, para que possamos aumentar a segurança do ambiente.
Durante essa documentação adotaremos a seguinte nomenclatura:
Por questões de segurança, é recomendado que o poller do L2M seja executado com um usuário não
root. O usuário que fará as consultas na máquina remota é o mesmo do usado pelo script de
poller do L2M (veja sua configuração do CRON para maiores detalhes). Vamos supor que esse
usuário é o www-data
.
Execute os seguintes comandos para criação de um par de chaves SSH, sem senha, que será usada na execução de comandos remotos:
su - www-data
ssh-keygen -N "" -f ~/.ssh/id_rsa
Esse comando deve gerar dois arquivos:
~/.ssh/id_rsa
: chave privada que deve ser guardada em segredo~/.ssh/id_rsa.pub
: chave pública que será enviada para a máquina remotaUm exemplo do arquivo ~/.ssh/id_rsa.pub
é como segue:
ssh-rsa AAAAB3NzaC1yc .... 9UhMcP8JjQ== www-data@gerencia
Na máquina remota, certifique-se de que o login de root está permitido (pelo menos para execução de
comandos: parâmetro PermitRootLogin forced-commands-only
no sshd_config ).
Como root, execute os seguintes comandos (substitua a CHAVE pela chave publica SSH criada na máquina local, conforme passo anterior):
mkdir -p ~/.ssh cat > ~/.ssh/authorized_keys ssh-rsa AAAAB3NzaC1y.... CRTL+D
Agora, vamos restringir quais comandos podem ser executados com essa chave, para isso,
edite o arquivo ~/.ssh/authorized_keys
deixando-o parecido com o seguinte:
command="/usr/local/bin/check_ssh_cmd",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3NzaC1y....
Precisaremos criar o arquivo de checagem. Para isso, crie o arquivo chamado
/usr/local/bin/check_ssh_cmd
com o seguinte conteúdo:
#!/bin/sh case "$SSH_ORIGINAL_COMMAND" in *\&*) echo "Rejected" ;; *\(*) echo "Rejected" ;; *\{*) echo "Rejected" ;; *\;*) echo "Rejected" ;; *\<*) echo "Rejected" ;; *\`*) echo "Rejected" ;; "LANG=C /usr/sbin/arp -a -n") $SSH_ORIGINAL_COMMAND ;; "/usr/local/bin/drop-mac-iptables.sh"*) $SSH_ORIGINAL_COMMAND ;; *) echo "Rejected" ;; esac
Falta ainda criarmos os scripts de bloqueio e desbloqueio dos MACs, que usam o firewall Netfilter/IPTables
nativo do Linux. Para o script de bloqueio, crie o arquivo /usr/local/bin/drop-mac-iptables.sh
com o
seguinte conteúdo:
#!/bin/bash ACTION="$1" MAC="$2" INTERFACE="$3" CHAIN="DROP-MAC-L2M" NAME="drop-mac-iptables.conf" DIR="/usr/local/etc" [ -d "$DIR" ] || mkdir -p $DIR function usage(){ echo "FAIL:USAGE $0 add|del|load" exit 1 } case "$ACTION" in add) if [ -z "$MAC" -o -z "$INTERFACE" ]; then usage fi if [ -s "$DIR/$NAME" ] && grep -q "$MAC,$INTERFACE" "$DIR/$NAME" >/dev/null 2>&1; then echo "OK:mac already blocked" exit 0 fi echo "$MAC,$INTERFACE" >> "$DIR/$NAME" ;; del) if [ -z "$MAC" -o -z "$INTERFACE" ]; then usage fi [ -s "$DIR/$NAME" ] && sed -i "/$MAC,$INTERRFACE/d" "$DIR/$NAME" ;; load) ;; *) usage ;; esac iptables -L $CHAIN -n >/dev/null 2>&1 RES=$? if [ $RES -eq 0 ]; then iptables -F $CHAIN else iptables -N $CHAIN iptables -I FORWARD -j $CHAIN iptables -I INPUT -j $CHAIN iptables -A $CHAIN -j RETURN fi FAIL=0 if [ -s "$DIR/$NAME" ]; then for pair in `cat $DIR/$NAME`; do MAC=$(echo $pair | cut -d, -f1) INTERFACE=$(echo $pair | cut -d, -f2) iptables -I $CHAIN -i $INTERFACE -m mac --mac-source $MAC -j DROP >/dev/null 2>&1 RES=$? if [ $RES -ne 0 ]; then FAIL=$((FAIL+1)) fi done fi if [ $FAIL -gt 0 ]; then echo "FAIL:$FAIL fails" else echo "OK" fi exit 0
Dê permissão de execução ao script:
chmod +x /usr/local/bin/drop-mac-iptables.sh
ATENÇÃO: duas coisas importantes que você deve verificar para manter as máquinas bloqueadas enquanto a máquina remota estiver executando são:
/usr/local/bin/drop-mac-iptables.sh load
).
Você pode fazer isso adicionando o script ao arquivo /etc/rc.local
que é executado na inicialização
do sistema na maioria das distribuições.