Alain's Blog

  1. 首页
  2. 软件工具
  3. 正文

通过ping获取URL的IP地址,使用iptables进行端口NAT转发

2023年5月21日 1237点热度 1人点赞 0条评论

IPTABLES NAT

使用ping获取指定URL的IP地址,使用iptables进行NAT转发,使用Cron进行定时检查IP是否发生改变,理论上其他系统也同样支持本文方式。

转载请注明出处,本文仅用于学习交流,不对之处,恳请指正 ,部分图片摘取网络,如有侵权请联系

1. 系统环境

  1. Debian 11
  2. iptables v1.8.7 (nf_tables)

2. 环境配置

本文使用的是iptables进行端口转发,你也可以使用ufw等工具,我在其他文章中也有大概提及使用UFW防火墙进行端口转发方式

  1. Debian系统安装iptables iputils

    sudo apt-get update && apt-get install iptables iputils-ping
  2. CentOS7, OpenEuler安装iptables iputils

    sudo yum install iptables iputils
  3. CentOS8, OpenEuler安装iptables iputils

    sudo dnf install iptables iputils

3. 脚本代码

请根据实际情况对一些代码进行调整

  1. local_port # 你要访问的本机端口号
  2. remote_url # 你要NAT的目标URL地址
  3. remote_port # 你要NAT的目标端口
    至于为什么用英文注释,特殊处理罢了
  1. 编写脚本

    nano /etc/cron.d/iptablesnat.sh
  2. 写入以下代码

    #!/bin/bash
    
    current_time(){
        echo `date -d "@$(( $(date +%s) ))" +%Y/%m/%d' '%H:%M:%S`
    }
    
    get_internal_ip() {
        # Check for 10.x.x.x IP address
        ip_addr=$(ip addr show | grep -oP "(?<=inet\s)10(\.\d+){3}")
        if [[ -n $ip_addr ]]; then
            echo "$ip_addr"
            return
        fi
    
        # Check for 172.x.x.x IP address if 10.x.x.x IP address is not found
        ip_addr=$(ip addr show | grep -oP "(?<=inet\s)172\.(1[6-9]|2[0-9]|3[0-1])(\.\d+){2}")
        if [[ -n $ip_addr ]]; then
            echo "$ip_addr"
            return
        fi
    
        # Check for 192.168.x.x IP address if 10.x.x.x and 172.x.x.x IP addresses are not found
        ip_addr=$(ip addr show | grep -oP "(?<=inet\s)192\.168(\.\d+){2}")
        if [[ -n $ip_addr ]]; then
            echo "$ip_addr"
            return
        fi
    }
    
    internal_ip=$(get_internal_ip)
    
    if [[ -n $internal_ip ]]; then
        echo "Internal IP Address: $internal_ip"
    else
        echo "No internal IP address found."
        exit 1
    fi
    
    # Port number to use, it is recommended to use special ports like 443 or 3389 to avoid suspicion
    local_port=change_to_your_port
    
    # The remote URL address to forward to
    remote_url=change_to_your_url
    
    # The remote port to forward to, usually 443
    remote_port=change_to_your_prot
    
    # Path to save the log file
    log_file="/var/log/iptablesnat.log"
    
    # Path to save the IP address obtained from the URL
    old_ip_file="/var/log/iptablesnat.oldip"
    
    echo "===================IPTABLES===================" >> $log_file
    
    if [ ! -f "$old_ip_file" ];then
        touch $old_ip_file
        echo "$(current_time) [I] Created IP file" >> $log_file
    fi
    
    realIP=$(ping $remote_url -c 1 -w 1 | sed '1{s/[^(]*(//;s/).*//;q}')
    echo "$(current_time) [I] Current IP: $realIP" >> $log_file
    oldIP=`cat $old_ip_file`
    echo "$(current_time) [I] Old IP: $oldIP" >> $log_file
    if [[ "$realIP" == "$oldIP" ]];then
        echo "$(current_time) [I] Current IP same as old IP, skipping..." >> $log_file
    else
        if [ -n "$oldIP" ]; then
            remote=$oldIP
            echo "$(current_time) [W] Delete the old iptables rules..." >> $log_file
            iptables -t nat -D PREROUTING -p tcp --dport $local_port -j DNAT --to-destination $remote:$remote_port
            iptables -t nat -D PREROUTING -p udp --dport $local_port -j DNAT --to-destination $remote:$remote_port
            iptables -t nat -D POSTROUTING -p tcp -d $remote --dport $remote_port -j SNAT --to-source $internal_ip
            iptables -t nat -D POSTROUTING -p udp -d $remote --dport $remote_port -j SNAT --to-source $internal_ip
        fi
    
        remote=$realIP
        echo "$(current_time) [W] Create the new iptables rules..." >> $log_file
        iptables -t nat -A PREROUTING -p tcp --dport $local_port -j DNAT --to-destination $remote:$remote_port
        iptables -t nat -A PREROUTING -p udp --dport $local_port -j DNAT --to-destination $remote:$remote_port
        iptables -t nat -A POSTROUTING -p tcp -d $remote --dport $remote_port -j SNAT --to-source $internal_ip
        iptables -t nat -A POSTROUTING -p udp -d $remote --dport $remote_port -j SNAT --to-source $internal_ip
    
        echo "=======================================" >> $log_file
        echo "$(iptables -t nat -L -n --line-numbers)" >> $log_file
        echo "=======================================" >> $log_file
    
        echo "$(current_time) [W] Save current IP to the log file" >> $log_file
        echo $remote > $old_ip_file
        echo "$(current_time) [I] Completed!" >> $log_file
    fi

4. 创建定时脚本

  1. 使用nano打开定时文件

    nano /etc/crontab
  2. 最后加入以下代码

    # Automatically obtain the IP that requires NAT from the URL
    @reboot      root /etc/cron.d/iptablesnat.sh
    */15 * * * * root /etc/cron.d/iptablesnat.sh

5. 修改本地host或者路由器的DHCP

如果转发到的目标Url不是你自己的,且你又希望开启TLS加密,那么你可以修改本地的host,或者在你的路由器的DHCP拦截对应的URL到你的服务器IP,或者如果你有类似Adguard Home或者SmartDNS之类的服务,那么你也可以在其中进行拦截

特别鸣谢

https://chat.openai.com/

标签: iptables Linux nat
最后更新:2023年5月28日

Alain

看了我的文,就是我的人,点个赞再走成不成

点赞
< 上一篇
下一篇 >

文章评论

取消回复

文章目录
  • 1. 系统环境
  • 2. 环境配置
  • 3. 脚本代码
  • 4. 创建定时脚本
  • 5. 修改本地host或者路由器的DHCP
  • 特别鸣谢

COPYRIGHT © 2022 Alain's Blog. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang