UFW: Autoriser le trafic uniquement d'un domaine avec une adresse IP dynamique

32

Je lance un VPS que je voudrais sécuriser avec UFW, en autorisant les connexions uniquement avec le port 80. Cependant, pour pouvoir l’administrer à distance, je dois garder le port 22 ouvert et le rendre accessible de chez moi.

Je sais que UFW peut être configuré pour autoriser les connexions à un port uniquement à partir d'une adresse IP spécifique:

ufw allow proto tcp from 123.123.123.123 to any port 22

Mais mon adresse IP est dynamique, ce n'est donc pas encore la solution.

La question est: j'ai une résolution DNS dynamique avec DynDNS, est-il possible de créer une règle en utilisant le domaine au lieu de l'adresse IP?

J'ai déjà essayé ceci:

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

mais j'ai eu ERROR: Bad source address

Carles Sala
la source

Réponses:

47

Je ne crois pas que ce soit possible avec ufw. ufwn’est qu’une interface pour iptableslaquelle cette fonctionnalité manque également; une solution serait donc de créer une entrée dans la crontab qui serait périodiquement exécutée et vérifie si l’adresse IP a changé. Si c'est le cas, il le mettra à jour.

Vous pourriez être tenté de faire ceci:

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

Mais cela résoudra le nom d'hôte en une adresse IP et l'utilisera pour la règle. Ainsi, si l'adresse IP change ultérieurement, cette règle deviendra invalide.

Idée alternative

Vous pouvez créer un script comme suit 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

source: utilisation d'IPTables avec des noms d'hôte IP dynamiques tels que dyndns.org

Avec ce script enregistré, vous pouvez créer une entrée de fichier crontab comme dans le fichier /etc/crontab:

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

Cette entrée exécute ensuite le script toutes les 5 minutes, en vérifiant si l'adresse IP attribuée au nom d'hôte a changé. Si c'est le cas, il créera une nouvelle règle l'autorisant, tout en supprimant l'ancienne règle pour l'ancienne adresse IP.

slm
la source
2
Quelle bêtise de ne pas avoir pensé à résoudre le nom d'hôte périodiquement. J'ai modifié votre script (ajout de journalisation, etc.) et cela fonctionne à merveille. Merci!
Carles Sala
@CarlesSala - content d'avoir résolu votre problème. En plus d'accepter, vous pouvez également voter par 8).
slm
1
note: sur Debian 7, j'ai dû changer de ligne Current_IP=$(host $HOSTNAME | cut -f4 -d' ')pourCurrent_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
Krystian, le
Est-ce que je pourrai voir cela en utilisant ufw status verbose? Je veux dire, les règles?
Freedo
@ Freedo pas sûr, essayez et voyez ce qui se passe.
slm
8

Je sais que cela est vieux, mais je l’ai rencontré et j’ai fini avec cette solution, ce qui semble encore meilleur, car aucun fichier journal n’est nécessaire et il est très facile d’ajouter des hôtes supplémentaires au besoin. Fonctionne comme un charme!

Source: 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
la source
désolé je suis un petit débutant. Où dois-je stocker ce script et où je change les choses pour refléter mon cas spécifique?
Freedo
5

Sur la base des réponses précédentes, j’ai mis à jour ce qui suit comme script bash qui fonctionne sous 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
la source
Cela pourrait même être ajouté pour cronle faire fonctionner périodiquement de son côté.
Tim Kennedy
C'est ce que j'ai fait;)
Mattias Pettersson
Ce script a un petit problème: lors de la première utilisation, si vous avez oublié de vous lancer en tant que root, il créera le fichier journal sans ajouter les règles. Ensuite, si vous exécutez à nouveau en tant que root, il vous suffira de dire «l'adresse IP n'a pas changé». Il doit être exécuté en tant que root la première fois! Aussi, il serait bon de changer LOGFILE=$HOME/ufw.logpour LOGFILE=$HOME/ufw.$HOSTNAME.logpermettre à plus d'un script d'être exécuté en même temps
Guerlando OCs
@GuerlandoOCs comment réinitialisez-vous si vous rencontrez ce problème?
Matthieu
0

Basé sur toutes les réponses avant que je les combine. Aucun fichier journal nécessaire. Testé sur 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

Vous pouvez ajouter un port aux règles avec le paramètre "port". par exemple:

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
la source