端口转发原理h2
端口转发(Port Forwarding), 也称为端口映射(Port Mapping),是一种网络技术,它允许将网络流量从一个 IP 地址和端口重定向到另一个 IP 地址和端口。 在 Linux 系统中, 我们通常使用 iptables 工具来实现端口转发。
基础防火墙规则配置h2
在开始配置端口转发之前,我们需要先配置一些基础的防火墙规则,包括开启 IP 转发、允许转发流量和配置 NAT 表。
echo 1 > /proc/sys/net/ipv4/ip_forward           # 开启 IP 转发iptables -A FORWARD -j ACCEPT                    # 允许转发iptables -t nat -A POSTROUTING   -j MASQUERADE   # 配置 NAT 表解释:
- echo 1 > /proc/sys/net/ipv4/ip_forward: 开启 IP 转发功能,允许 Linux 系统作为路由器转发数据包。
- iptables -A FORWARD -j ACCEPT: 允许所有转发流量通过防火墙,即允许从一个网卡转发到另一个网卡的数据包。
- iptables -t nat -A POSTROUTING -j MASQUERADE: 配置网络地址转换(NAT), 将转发的数据包的源 IP 地址转换为本机 IP 地址,以便目标机器能够正常响应。
添加端口转发规则h2
以下示例展示了如何将本地端口 80 的流量转发到 192.168.2.123 的 80 端口。
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.2.123:80iptables -t nat -A POSTROUTING -p tcp -d 192.168.2.123 --dport 80 -j MASQUERADE解释:
- iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.2.123:80:- -t nat: 指定操作的表为 NAT 表,用于网络地址转换。
- -A PREROUTING: 将规则添加到- PREROUTING链,该链用于处理进入本机的数据包。
- -p tcp: 指定协议为 TCP。
- --dport 80: 指定目标端口为 80。
- -j DNAT: 执行目标地址转换(DNAT)。
- --to-destination 192.168.2.123:80: 将目标地址转换为- 192.168.2.123:80。
 
- iptables -t nat -A POSTROUTING -p tcp -d 192.168.2.123 --dport 80 -j MASQUERADE:- -t nat: 指定操作的表为 NAT 表。
- -A POSTROUTING: 将规则添加到- POSTROUTING链,该链用于处理即将离开本机的数据包。
- -p tcp: 指定协议为 TCP。
- -d 192.168.2.123: 指定目标 IP 地址为- 192.168.2.123。
- --dport 80: 指定目标端口为80.
- -j MASQUERADE: 执行地址伪装,将源 IP 地址转换为本机 IP 地址。
 
删除端口转发规则h2
以下示例展示了如何删除将本地端口 80 的流量转发到 192.168.2.123 的 80 端口的规则。
iptables -t nat -D PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.2.123:80iptables -t nat -D POSTROUTING -p tcp -d 192.168.2.123 --dport 80 -j MASQUERADE解释:
- 与添加规则类似,只是将 -A改为-D,表示删除规则。
查看转发规则h2
使用以下命令可以查看当前配置的端口转发规则:
iptables -t nat -L -n解释:
- -t nat: 指定查看 NAT 表。
- -L: 列出规则。
- -n: 使用数字格式显示 IP 地址和端口,而不是使用主机名和服务名。
端口转发管理脚本h2
为了方便管理端口转发规则,我们提供了一个 forward_port 脚本。 该脚本可以帮助您更方便地添加、删除和查看转发规则。
使用方法h3
以下是一些脚本的使用示例:
root@localhost:~# forward_port list当前端口转发规则列表:----------------------------------------[TCP] 本地端口: 8000 转发目标: 192.168.2.142:8000root@localhost:~# forward_port  add tcp 8001  100.88.88.104 8000添加完成root@localhost:~# forward_port list当前端口转发规则列表:----------------------------------------[TCP] 本地端口: 8000 转发目标: 192.168.2.142:8000[TCP] 本地端口: 8001 转发目标: 100.88.88.104:8000root@localhost:~# forward_port  del tcp 8001删除完成root@localhost:~# forward_port list当前端口转发规则列表:----------------------------------------[TCP] 本地端口: 8000 转发目标: 192.168.2.142:8000脚本代码h3
以下是 forward_port 脚本的完整代码:
#!/bin/bash
# 检查是否具有 root 权限if [ "$EUID" -ne 0 ]; then    echo "请使用 sudo 运行此脚本"    exit 1fi
# 显示帮助信息show_help() {    echo "用法:"    echo "  $0 list                     # 显示所有端口转发规则"    echo "  $0 add tcp|udp 本地端口 目标IP 目标端口  # 添加转发规则"    echo "  $0 del tcp|udp 本地端口     # 删除转发规则"    echo ""    echo "示例:"    echo "  $0 add tcp 8080 192.168.1.100 80"    echo "  $0 del tcp 8080"}
# 列出当前转发规则list_forwards() {    # 获取 PREROUTING 规则    rules=$(iptables -t nat -L PREROUTING -n --line-numbers | grep "dpt:" | grep "to:")
    if [ -z "$rules" ]; then        echo "当前没有端口转发规则"        return    fi
    echo "当前端口转发规则列表:"    echo "----------------------------------------"
    while IFS= read -r line; do        # 提取规则信息        protocol=$(echo "$line" | grep -o 'tcp\|udp' | tr '[:lower:]' '[:upper:]')        local_port=$(echo "$line" | grep -o 'dpt:[0-9]*' | cut -d':' -f2)        target=$(echo "$line" | grep -o 'to:[0-9.]*:[0-9]*' | cut -d':' -f2,3)
        if [ ! -z "$protocol" ] && [ ! -z "$local_port" ] && [ ! -z "$target" ]; then            target_ip=$(echo "$target" | cut -d':' -f1)            target_port=$(echo "$target" | cut -d':' -f2)            echo "[$protocol] 本地端口: $local_port 转发目标: $target_ip:$target_port"        fi    done <<< "$rules"}
# 检查转发规则是否已存在check_forward_exists() {    local proto=$1    local port=$2
    iptables -t nat -L PREROUTING -n | grep "dpt:$port" | grep -q "$proto"    return $?}
# 添加转发规则add_forward() {    local proto=$1    local local_port=$2    local target_ip=$3    local target_port=$4
    # 验证参数    if [[ ! "$proto" =~ ^(tcp|udp)$ ]]; then        echo "错误: 协议必须是 tcp 或 udp"        return 1    fi
    if [[ ! "$local_port" =~ ^[0-9]+$ ]] || [ "$local_port" -lt 1 ] || [ "$local_port" -gt 65535 ]; then        echo "错误: 无效的端口号 $local_port"        return 1    fi
    if [[ ! "$target_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then        echo "错误: 无效的 IP 地址 $target_ip"        return 1    fi
    if [[ ! "$target_port" =~ ^[0-9]+$ ]] || [ "$target_port" -lt 1 ] || [ "$target_port" -gt 65535 ]; then        echo "错误: 无效的目标端口号 $target_port"        return 1    fi
    # 检查规则是否已存在    if check_forward_exists "$proto" "$local_port"; then        echo "${proto^^} $local_port 已经有转发规则了"        return 1    fi
    # 添加转发规则    iptables -t nat -A PREROUTING -p "$proto" --dport "$local_port" -j DNAT --to-destination "$target_ip:$target_port"    iptables -t nat -A POSTROUTING -p "$proto" -d "$target_ip" --dport "$target_port" -j MASQUERADE
    if [ $? -eq 0 ]; then        echo "添加完成"    else        echo "添加失败"        return 1    fi}
# 删除转发规则del_forward() {    local proto=$1    local port=$2
    # 验证参数    if [[ ! "$proto" =~ ^(tcp|udp)$ ]]; then        echo "错误: 协议必须是 tcp 或 udp"        return 1    fi
    if [[ ! "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then        echo "错误: 无效的端口号 $port"        return 1    fi
    # 检查规则是否存在    if ! check_forward_exists "$proto" "$port"; then        echo "未找到 ${proto^^} 端口 $port 的转发规则"        return 1    fi
    # 获取目标地址信息用于删除 POSTROUTING 规则    target_info=$(iptables -t nat -L PREROUTING -n | grep "dpt:$port" | grep "$proto")    target_ip=$(echo "$target_info" | grep -o 'to:[0-9.]*:[0-9]*' | cut -d':' -f2)    target_port=$(echo "$target_info" | grep -o 'to:[0-9.]*:[0-9]*' | cut -d':' -f3)
    # 删除规则    iptables -t nat -D PREROUTING -p "$proto" --dport "$port" -j DNAT --to-destination "$target_ip:$target_port" 2>/dev/null    iptables -t nat -D POSTROUTING -p "$proto" -d "$target_ip" --dport "$target_port" -j MASQUERADE 2>/dev/null
    if [ $? -eq 0 ]; then        echo "删除完成"    else        echo "删除失败"        return 1    fi}
# 主程序case "$1" in    list)        list_forwards        ;;    add)        if [ $# -ne 5 ]; then            echo "错误: add 命令需要4个参数"            show_help            exit 1        fi        add_forward "$2" "$3" "$4" "$5"        ;;    del)        if [ $# -ne 3 ]; then            echo "错误: del 命令需要2个参数"            show_help            exit 1        fi        del_forward "$2" "$3"        ;;    *)        show_help        exit 1        ;;esac
exit 0脚本使用说明:
- forward_port list: 列出当前所有端口转发规则。
- forward_port add tcp|udp 本地端口 目标IP 目标端口: 添加新的端口转发规则。- tcp|udp: 指定协议。
- 本地端口: 要监听的本地端口。
- 目标IP: 要转发的目标 IP 地址。
- 目标端口: 要转发的目标端口。
 
- forward_port del tcp|udp 本地端口: 删除指定的端口转发规则。- tcp|udp: 指定协议。
- 本地端口: 要删除的转发规则对应的本地端口。
 
总结h2
本文档介绍了如何在 Linux 系统中配置端口转发,包括手动配置 iptables 规则以及使用提供的 forward_port 脚本进行管理。希望这些内容能够帮助您更好地理解和使用 Linux 的端口转发功能。
