UFW: Permitir tráfego apenas de um domínio com endereço IP dinâmico

32

Eu executo um VPS que gostaria de proteger usando o UFW, permitindo conexões apenas à porta 80. No entanto, para poder administrá-lo remotamente, preciso manter a porta 22 aberta e torná-la acessível a partir de casa.

Eu sei que o UFW pode ser configurado para permitir conexões a uma porta apenas a partir de um endereço IP específico:

ufw allow proto tcp from 123.123.123.123 to any port 22

Mas meu endereço IP é dinâmico, então essa ainda não é a solução.

A pergunta é: Eu tenho resolução dinâmica de DNS com o DynDNS, então é possível criar uma regra usando o domínio em vez do IP?

Eu já tentei isso:

ufw allow proto tcp from mydomain.dyndns.org to any port 22

mas eu tenho ERROR: Bad source address

Carles Sala
fonte

Respostas:

47

Não acredito que isso seja possível ufw. ufwé apenas uma interface para a iptablesqual também não há esse recurso, portanto, uma abordagem seria criar uma entrada crontab que seria executada periodicamente e verificar se o endereço IP foi alterado. Se tiver, ele será atualizado.

Você pode ser tentado a fazer isso:

$ iptables -A INPUT -p tcp --src mydomain.dyndns.org --dport 22 -j ACCEPT

Mas isso resolverá o nome do host para um IP e o utilizará para a regra, portanto, se o IP mudar posteriormente, essa regra se tornará inválida.

Idéia alternativa

Você pode criar um script como esse, chamado iptables_update.bash,.

#!/bin/bash
#allow a dyndns name

HOSTNAME=HOST_NAME_HERE
LOGFILE=LOGFILE_NAME_HERE

Current_IP=$(host $HOSTNAME | cut -f4 -d' ')

if [ $LOGFILE = "" ] ; then
  iptables -I INPUT -i eth1 -s $Current_IP -j ACCEPT
  echo $Current_IP > $LOGFILE
else

  Old_IP=$(cat $LOGFILE)

  if [ "$Current_IP" = "$Old_IP" ] ; then
    echo IP address has not changed
  else
    iptables -D INPUT -i eth1 -s $Old_IP -j ACCEPT
    iptables -I INPUT -i eth1 -s $Current_IP -j ACCEPT
    /etc/init.d/iptables save
    echo $Current_IP > $LOGFILE
    echo iptables have been updated
  fi
fi

fonte: Usando IPTables com nomes de host de IP dinâmico como dyndns.org

Com esse script salvo, você pode criar uma entrada crontab como esta no arquivo /etc/crontab:

*/5 * * * * root /etc/iptables_update.bash > /dev/null 2>&1

Essa entrada executaria o script a cada 5 minutos, verificando se o endereço IP atribuído ao nome do host foi alterado. Nesse caso, ele criará uma nova regra permitindo, enquanto exclui a regra antiga para o endereço IP antigo.

slm
fonte
2
Que tolice eu não ter pensado em resolver o nome do host periodicamente. Modifiquei seu script (registro adicionado, etc.) e funciona como um encanto. Obrigado!
Carles Sala
@CarlesSala - que bom que resolveu o seu problema. Além de aceitar, você também pode votar 8-).
slm
1
nota: no Debian 7 I teve para a linha de mudança Current_IP=$(host $HOSTNAME | cut -f4 -d' ')paraCurrent_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
Krystian
Serei capaz de ver isso ao usar o status ufw detalhado? Quero dizer, as regras?
Freedo
@ Freedo não tenho certeza, tente e veja o que acontece.
Slm
8

Eu sei que isso é antigo, mas eu o encontrei e acabei com essa solução no final, o que parece ainda melhor porque nenhum arquivo de log é necessário e é muito fácil adicionar hosts adicionais conforme necessário. Funciona como um encanto!

Fonte: http://rdstash.blogspot.ch/2013/09/allow-host-with-dynamic-ip-through.html

#!/bin/bash

DYNHOST=$1
DYNHOST=${DYNHOST:0:28}
DYNIP=$(host $DYNHOST | grep -iE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" |cut -f4 -d' '|head -n 1)

# Exit if invalid IP address is returned
case $DYNIP in
0.0.0.0 )
exit 1 ;;
255.255.255.255 )
exit 1 ;;
esac

# Exit if IP address not in proper format
if ! [[ $DYNIP =~ (([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ]]; then
exit 1
fi

# If chain for remote doesn't exist, create it
if ! /sbin/iptables -L $DYNHOST -n >/dev/null 2>&1 ; then
/sbin/iptables -N $DYNHOST >/dev/null 2>&1
fi

# Check IP address to see if the chain matches first; skip rest of script if update is not needed
if ! /sbin/iptables -n -L $DYNHOST | grep -iE " $DYNIP " >/dev/null 2>&1 ; then


# Flush old rules, and add new
/sbin/iptables -F $DYNHOST >/dev/null 2>&1
/sbin/iptables -I $DYNHOST -s $DYNIP -j ACCEPT

# Add chain to INPUT filter if it doesn't exist
if ! /sbin/iptables -C INPUT -t filter -j $DYNHOST >/dev/null 2>&1 ; then
/sbin/iptables -t filter -I INPUT -j $DYNHOST
fi

fi
Dom
fonte
desculpe, eu sou um pouco novato. Onde eu preciso armazenar esse script e onde eu mudo as coisas para refletir meu caso específico?
Freedo
5

Com base nas respostas anteriores, atualizei o seguinte como script bash que funciona no Debian Jessie

#!/bin/bash
HOSTNAME=dynamichost.domain.com
LOGFILE=$HOME/ufw.log
Current_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')

if [ ! -f $LOGFILE ]; then
    /usr/sbin/ufw allow from $Current_IP to any port 22 proto tcp
    echo $Current_IP > $LOGFILE
else

    Old_IP=$(cat $LOGFILE)
    if [ "$Current_IP" = "$Old_IP" ] ; then
        echo IP address has not changed
    else
        /usr/sbin/ufw delete allow from $Old_IP to any port 22 proto tcp
        /usr/sbin/ufw allow from $Current_IP to any port 22 proto tcp
        echo $Current_IP > $LOGFILE
        echo iptables have been updated
    fi
fi
Mattias Pettersson
fonte
Isso pode até ser adicionado para cronque seja executado periodicamente por conta própria.
Tim Kennedy
Isso é o que eu fiz;)
Mattias Pettersson
Esse script tem um pequeno problema: no primeiro uso, se você esquecer de executar como root, ele criará o arquivo de log, mas não adicionará as regras. Então, se você executar novamente como root, ele dirá apenas 'endereço IP não mudou'. Ele deve ser executado como root pela primeira vez! Além disso, seria bom para a mudança LOGFILE=$HOME/ufw.logpara LOGFILE=$HOME/ufw.$HOSTNAME.logpermitir mais de uma execução de script ao mesmo tempo
Guerlando OCs
@GuerlandoOCs como você redefine se você se deparar com esse problema?
28418 Matthew
0

Com base em todas as respostas antes de eu combiná-las. Nenhum arquivo de log necessário. Testado no Ubuntu 18.04

#!/bin/bash
HOSTNAME=YOUR.DNS.NAME.HERE

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root"
   exit 1
fi

new_ip=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
old_ip=$(/usr/sbin/ufw status | grep $HOSTNAME | head -n1 | tr -s ' ' | cut -f3 -d ' ')

if [ "$new_ip" = "$old_ip" ] ; then
    echo IP address has not changed
else
    if [ -n "$old_ip" ] ; then
        /usr/sbin/ufw delete allow from $old_ip to any
    fi
    /usr/sbin/ufw allow from $new_ip to any comment $HOSTNAME
    echo iptables have been updated
fi

Você pode adicionar uma porta às regras com o parâmetro "port". por exemplo:

if [ -n "$old_ip" ] ; then
    /usr/sbin/ufw delete allow from $old_ip to any port 22
fi
/usr/sbin/ufw allow from $new_ip to any port 22 comment $HOSTNAME
Sebastian
fonte