Logo
10 mins
Linux 本地端口转发到其他机器( 附带管理脚本)

本文介绍了Linux系统端口转发 的原理和操作,包括如何使用iptables配 置基础防火墙规则、添加/删除端 口转发规则,以及通过forward_port脚本 便捷管理转发条目。

Linux 本地端口转发到其他机器(  附带管理脚本)

端口转发原理h2

端口转发(Port Forwarding), 也称为端口映射(Port Mapping),是一种网络技术,它允许将网络流量从一个 IP 地址和端口重定向到另一个 IP 地址和端口。 在 Linux 系统中, 我们通常使用 iptables 工具来实现端口转发。


基础防火墙规则配置h2

在开始配置端口转发之前,我们需要先配置一些基础的防火墙规则,包括开启 IP 转发、允许转发流量和配置 NAT 表。

Terminal window
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 端口。

Terminal window
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.2.123:80
iptables -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 端口的规则。

Terminal window
iptables -t nat -D PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.2.123:80
iptables -t nat -D POSTROUTING -p tcp -d 192.168.2.123 --dport 80 -j MASQUERADE

解释:

  • 与添加规则类似,只是将 -A 改为 -D,表示删除规则。

查看转发规则h2

使用以下命令可以查看当前配置的端口转发规则:

Terminal window
iptables -t nat -L -n

解释:

  • -t nat: 指定查看 NAT 表。
  • -L: 列出规则。
  • -n: 使用数字格式显示 IP 地址和端口,而不是使用主机名和服务名。

端口转发管理脚本h2

为了方便管理端口转发规则,我们提供了一个 forward_port 脚本。 该脚本可以帮助您更方便地添加、删除和查看转发规则。


使用方法h3

以下是一些脚本的使用示例:

Terminal window
root@localhost:~# forward_port list
当前端口转发规则列表:
----------------------------------------
[TCP] 本地端口: 8000 转发目标: 192.168.2.142:8000
root@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:8000
root@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 1
fi
# 显示帮助信息
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 的端口转发功能。