UFW:仅允许来自具有动态IP地址的域的流量


32

我运行了一个我想使用UFW进行保护的VPS,仅允许连接到端口80。但是,为了能够对其进行远程管理,我需要保持端口22的开放状态并使其可在家中访问。

我知道UFW可以配置为仅允许从特定IP地址连接到端口:

ufw allow proto tcp from 123.123.123.123 to any port 22

但是我的IP地址是动态的,因此这不是解决方案。

问题是:我具有DynDNS的动态DNS解析功能,是否可以使用域而不是IP创建规则?

我已经试过了:

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

但是我得到了 ERROR: Bad source address

Answers:


47

我认为不可能做到ufwufw只是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与dyndns.org等动态IP主机名一起使用

保存此脚本后,您可以在文件中创建一个crontab条目,如下所示/etc/crontab

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

然后,该条目将每5分钟运行一次脚本,检查分配给主机名的IP地址是否已更改。如果是这样,它将在删除旧IP地址的旧规则的同时创建允许它的新规则。


2
我没有想到要定期解析主机名,这真是愚蠢。我修改了您的脚本(添加了日志记录等),它的工作原理很吸引人。谢谢!
Carles Sala 2013年

@CarlesSala-很高兴它解决了您的问题。除了接受之外,您还可以投票赞成8-)。
slm

1
注意:在Debian 7上,我不得不将行更改Current_IP=$(host $HOSTNAME | cut -f4 -d' ')Current_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
Krystian

使用ufw status冗长时,我能看到这个吗?我是说,规则?
Freedo

@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

对不起,我是个新手。我需要在哪里存储此脚本,以及在哪里进行更改以反映我的特定情况?
Freedo

5

根据先前的答案,我将以下内容更新为可在Debian Jessie上使用的bash脚本

#!/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它以使其自己定期运行。
蒂姆·肯尼迪

那就是我所做的;)
Mattias Pettersson

这个脚本有一个小问题:第一次使用时,如果您忘记以root身份运行,它将创建日志文件,但不添加规则。然后,如果您再次以root用户身份运行,则只会说“ ip地址未更改”。它必须在第一时间以root身份运行!另外,最好更改LOGFILE=$HOME/ufw.logLOGFILE=$HOME/ufw.$HOSTNAME.log允许同时运行多个脚本
Guerlando OCs '18

@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”参数将端口添加到规则中。例如:

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.