UFW: Дозволити трафік лише з домену з динамічною IP-адресою


32

Я запускаю VPS, який я хотів би захистити за допомогою UFW, дозволяючи з'єднання лише до порту 80. Однак для того, щоб мати змогу адміністративно управляти ним, мені потрібно тримати порт 22 відкритим і зробити його доступним з дому.

Я знаю, що UFW можна налаштувати так, щоб дозволити з'єднання до порту лише з певної IP-адреси:

ufw allow proto tcp from 123.123.123.123 to any port 22

Але моя IP-адреса динамічна, тому це ще не є рішенням.

Питання: у мене динамічна роздільна здатність DNS з DynDNS, тож чи можна створити правило, використовуючи домен замість IP?

Я вже спробував це:

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

але я отримав ERROR: Bad source address

Відповіді:


47

Я не вірю, що це можливо ufw. ufwце лише фронтенд, до iptablesякого також не вистачає цієї функції, тому одним із підходів було б створити запис crontab, який періодично запускався і перевіряв би, чи змінилася IP-адреса. Якщо він є, він оновить його.

Вас може спокусити це зробити:

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

Але це дозволить вирішити ім'я хоста для IP та використовувати його для правила, тому, якщо IP пізніше зміниться, це правило стане недійсним.

Альтернативна ідея

Ви можете створити сценарій , як це так, називається, 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

джерело: Використання IPTables з динамічними іменами хостів IP, як dyndns.org

За допомогою цього збереженого скрипту ви можете створити запис із записом на кронтабі, як у файлі /etc/crontab:

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

Потім цей запис буде виконувати сценарій кожні 5 хвилин, перевіряючи, чи змінилася IP-адреса, призначена імені хоста. Якщо так, то воно створить нове правило, що дозволяє йому, при цьому видаляючи старе правило для старої IP-адреси.


2
Як нерозумно, що я не думав періодично вирішувати ім'я хоста. Я змінив ваш сценарій (додав реєстрацію тощо), і він працює як шарм. Дякую!
Карлес Сала

@CarlesSala - рада, що вирішила вашу проблему. На додаток до прийняття ви можете також підняти 8–8).
slm

1
зауважте: на Debian 7 мені довелося змінити лінію Current_IP=$(host $HOSTNAME | cut -f4 -d' ')наCurrent_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
Кристіян

Чи зможу я побачити це під час використання багатословного статусу ufw? Я маю на увазі, правила?
Фредо

@Freedo не впевнений, спробуйте і подивіться, що станеться.
slm

8

Я знаю, що це старе, але я наткнувся на це і в кінцевому підсумку вирішив це рішення, що здається ще кращим, оскільки не потрібен файл журналу і дуже легко додавати додаткові хости за потребою. Працює як шарм!

Джерело: 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

вибачте, я маленький новачок. Де мені потрібно зберігати цей сценарій і де я міняю речі, щоб відобразити мій конкретний випадок?
Фредо

5

На підставі попередніх відповідей я оновив наступний текст як баш сценарій, який працює над 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

До цього можна навіть додати, щоб cronвін періодично працював самостійно.
Тім Кеннеді

Це я і зробив;)
Маттіас Петтерссон

У цього сценарію є невелика проблема: при першому використанні, якщо ви забули запустити як root, він створить файл журналу, але не додасть правила. Тоді якщо ви запустите знову як root, він просто скаже «ip address не змінилася». Його потрібно запустити як root вперше! Крім того, було б добре змінити, LOGFILE=$HOME/ufw.logщоб LOGFILE=$HOME/ufw.$HOSTNAME.logдозволити запускати більше одного сценарію одночасно
Oers Guerlando

@GuerlandoOCs, як зробити скидання, якщо у вас виникнуть проблеми?
Матвій

0

На основі всіх відповідей, перш ніж я їх поєднав. Журнал не потрібен. Тестовано на 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

Ви можете додати порт до правил з параметром "port". eG:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.