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.