【问题标题】:Struggling with Linux IPTables with dynamic IP与动态 IP 的 Linux IPTables 斗争
【发布时间】:2021-06-18 03:09:21
【问题描述】:

我构建了一个与 API 对话的服务器;但是,端点没有静态 IP。我已经能够成功创建一个 bash 文件,该文件将查询 ip,将其写入日志,然后即时更改 iptables。由于这是写入磁盘,我不想这样做。

工作原理:这段代码将向 iptables 列表写入一个条目。

什么不起作用:每次我运行它时它都会继续运行。如果条目已经存在,我想删除它。

这里是没有日志文件的代码:

#!/bin/bash

IPT="/sbin/iptables"

HOSTNAME=google.com

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=$($IPT -L -n --line-number | grep $HOSTNAME | head -1 | tr -s ' ' | cut -f5 -d ' ')

if [ "$new_ip" = "$old_ip" ] ; then
        echo "first if statment"
        #echo IP address has not changed
else
        echo "first else"
        if [ -n "$old_ip" ] ; then
                echo "second if statement"
                $IPT -D OUTPUT -d $old_ip -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
                $IPT -D INPUT -s $old_ip -p tcp -m tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
        fi
        echo "generic if"
        $IPT -I OUTPUT -p tcp -d $new_ip --dport 443  -m state --state NEW,ESTABLISHED -j ACCEPT
        $IPT -I INPUT  -p tcp -s $new_ip --sport 443  -m state --state ESTABLISHED     -j ACCEPT
        #echo iptables have been updated
fi

这是带有日志文件的代码(不想使用):


#!/bin/bash

IPT="/sbin/iptables"

HOSTNAME=google.com
LOGFILE=/home/runrun/testing.log
Current_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')

if [ ! -f $LOGFILE ]; then
        echo "first if statement"
        $IPT -I OUTPUT -p tcp -d $Current_IP --dport 443  -m state --state NEW,ESTABLISHED -j ACCEPT
        $IPT -I INPUT  -p tcp -s $Current_IP --sport 443  -m state --state ESTABLISHED     -j ACCEPT
        echo $Current_IP > $LOGFILE
else
        echo "first else statement"
fi


Old_IP=$(cat $LOGFILE)
if [ "$Current_IP" = "$Old_IP" ] ; then
        echo "second if statement"
        #echo IP address has not changed
else
        echo "second else statement"
        $IPT -D OUTPUT -d $Old_IP -p tcp -m tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
        $IPT -D INPUT -s $Old_IP -p tcp -m tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT
        $IPT -I OUTPUT -p tcp -d $Current_IP --dport 443  -m state --state NEW,ESTABLISHED -j ACCEPT
        $IPT -I INPUT  -p tcp -s $Current_IP --sport 443  -m state --state ESTABLISHED     -j ACCEPT
        echo $Current_IP > $LOGFILE
        echo iptables have been updated
fi

【问题讨论】:

    标签: linux bash unix iptables


    【解决方案1】:

    您的脚本中没有日志的主要问题是在填充old_ip 变量时指定了-n 选项。 -n 指定 数字 主机名(例如 IP)。由于您尝试使用以下命令替换:

    old_ip=$($IPT -L -n --line-number | grep $HOSTNAME ...
    

    grep $HOSTNAME 永远不会匹配,因为 iptables 输出不包括主机名,只包括 IP。如果您不指定-n 并强制解析名称,iptables 命令可能需要几分钟来解析每个主机和网络块。手册页解释说最好避免(有充分理由)

    坦率地说,保留一个包含您感兴趣的最后一个 IP 的持久性文件(甚至是一个临时文件)(或者一个包含主机名 IP 对的文件,您可以使用它们来从 iptables 中删除旧 IP)可能是最有效的路要走。

    (不要忘记查看您的发行版如何/是否提供了一个持久性 iptable 配置文件,用于在重新启动时保留您的配置,如果提供,请在删除旧 IP 后使用更改更新持久性副本)

    【讨论】:

    • 当我运行脚本时,它总是向 iptables 添加一个条目。我删除了-n,它仍在向 iptables 添加一个条目。它永远不会删除任何东西。这是运行脚本时的输出 `user@computer:~ $ sudo ./nologfile_dns.sh first else generic if `
    • 如果您查看iptables -vL 的输出,您不会得到host.domain.tld,但您更有可能得到每个主机名的12-2348-some-net-blk-host.domain.tld 字符串。虽然它仍然会包含/匹配,例如google.com,它将提供的结果与您的 iptables 列表中的 host.domain.tld 不匹配。 (如果您也计时,则需要相当长的时间,尤其是如果您在网络块中阻止寻址范围等。)您为什么反对包含最后一个 IP 主机名信息的持久文件?跨度>
    • 当这个系统启动时,它有一个默认的 iptables 设置。它阻止一切,只允许 ssh 访问它。系统确实需要通过其 dns 名称在线访问服务器。那个ip地址变了。有没有办法用这个写一个无限循环?
    • 一般情况下,启动时读取的文件类似于iptables.rules,其中包含如下条目:-A INPUT -s 54.38.81.231/32 -j DROP。大多数发行版都提供了一种在进行更改时写入新的iptables.rules 文件(或类似文件)的方法,以便下次重新启动将加载最后的配置。如果我这样做,对于可能更改 IP 的主机(或主机),我会保留一个带有 host.domain.tld 111.222.333.444 对的短文件。然后在获取 IP 的对上进行一个短循环,并使用iptables -vL > /tmp/iptablestmp 进行一个循环,然后使用grep -q $theIP || ## handle new address for $theIP 在 IP 对上进行循环。
    【解决方案2】:

    我让它工作了。它不使用日志文件;一切都存储在内存中。您也可以将其作为 crontab 作业运行

    要求:iptables、dig 以及与评论“Google”匹配的 iptables 规则

    这是一个要添加的示例规则:

    sudo iptables -I OUTPUT -p tcp -d 7.7.7.7 --dport 443 -m comment --comment "Google" -m state --state NEW,ESTABLISHED -j ACCEPT
    

    这是一个每 5 分钟运行一次的 crontab 作业。放入PATH变量:

    PATH=/usr/sbin:/sbin:/usr/bin:/bin
    */5 * * * * /root/script.sh > /dev/null 2>&1
    

    这将检查 IP 地址,如果它改变了,它会更新它。我在网上找了这个,没有找到解决办法,但就是这样。

    PATH=/usr/sbin:/sbin:/usr/bin:/bin
    #!/bin/bash
    
    HOSTNAME=google.com
    
    if [[ $EUID -ne 0 ]]; then
       echo "This script must be run as root"
       exit 1
    fi
    
    new_ip=$(dig +short $HOSTNAME | head -n2)
    old_ip=$(/usr/sbin/iptables --line-number -nL OUTPUT | grep Google | cut -f26 -d ' ')
    
    
    if [ "$new_ip" = "$old_ip" ] ; then
        echo "IP address has not changed"
    else
        echo "IP address has been changed"
        echo "Updating IPTables now"
        DELETERULE=$(/usr/sbin/iptables --line-number -nL OUTPUT | grep Google | cut -f1 -d ' ' | sort -nr)
        for rules in $DELETERULE
        do
            /usr/sbin/iptables -D OUTPUT "$rules"
        done
        for ip in $new_ip
        do
            /usr/sbin/iptables -I OUTPUT -p tcp -d "$ip" --dport 443 -m comment --comment "Google" -m state --state NEW,ESTABLISHED -j ACCEPT
        done
    fi
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-29
      • 2020-09-18
      • 2018-05-23
      • 2013-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多