Linux 端口映射管理脚本

Linux 端口映射管理脚本
使用方法:bash port_map.sh

点击查看代码
#!/bin/bash

GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

if [ "$(id -u)" -ne 0 ]; then
    echo -e "${RED}请使用 root 权限运行${NC}"
    exit 1
fi

declare -A map_list
map_count=0

check_ip() {
    local ip=$1
    if [[ ! $ip =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then return 1; fi
    IFS=. read -r a b c d <<< "$ip"
    ((a>=0&&a<=255&&b>=0&&b<=255&&c>=0&&c<=255&&d>=0&&d<=255))
}

check_port() {
    local port=$1
    [[ $port =~ ^[0-9]+$ ]] && ((port >=1 && port <=65535))
}

enable_ip_forward() {
    echo 1 > /proc/sys/net/ipv4/ip_forward
    grep -q "net.ipv4.ip_forward=1" /etc/sysctl.conf || echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
    sysctl -p &>/dev/null
}

load_mapping_list() {
    map_list=()
    map_count=0
    local line

    while read line; do
        local dport to_ip to_port
        dport=$(echo "$line" | grep -oP 'dpt:\K\d+' 2>/dev/null | head -1)
        to=$(echo "$line" | grep -oP 'to-destination:\K[\d.]+:\d+' 2>/dev/null) || to=$(echo "$line" | grep -oP 'to:\K[\d.]+:\d+' 2>/dev/null)
        to_ip=${to%:*}
        to_port=${to#*:}

        if [ -n "$dport" ] && [ -n "$to_ip" ] && [ -n "$to_port" ]; then
            ((map_count++))
            map_list[$map_count]="$dport|$to_ip|$to_port"
        fi
    done < <(iptables -t nat -L PREROUTING 2>/dev/null | grep -E 'DNAT|to-destination')
}

show_mapping_list() {
    load_mapping_list
    echo -e "\n${GREEN}=== 当前端口映射列表 ===${NC}"
    echo -e "${YELLOW}序号   本机端口 → 目标IP:端口${NC}"
    echo "-----------------------------------------"
    if [ $map_count -eq 0 ]; then
        echo -e "${YELLOW}  暂无映射规则${NC}"
    else
        for i in "${!map_list[@]}"; do
            IFS='|' read -r dport to_ip to_port <<< "${map_list[$i]}"
            echo -e "  $i)   $dport → $to_ip:$to_port"
        done
    fi
    echo "-----------------------------------------"
}

add_forward() {
    local to_ip=$1
    local port=$2

    iptables -t nat -D PREROUTING -p tcp --dport "$port" -j DNAT --to-destination "${to_ip}:${port}" 2>/dev/null
    iptables -t nat -D POSTROUTING -d "$to_ip" -p tcp --dport "$port" -j MASQUERADE 2>/dev/null
    iptables -D FORWARD -p tcp -d "$to_ip" --dport "$port" -j ACCEPT 2>/dev/null

    iptables -t nat -A PREROUTING -p tcp --dport "$port" -j DNAT --to-destination "${to_ip}:${port}"
    iptables -t nat -A POSTROUTING -d "$to_ip" -p tcp --dport "$port" -j MASQUERADE
    iptables -A FORWARD -p tcp -d "$to_ip" --dport "$port" -j ACCEPT
    iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT 2>/dev/null
}

delete_forward_rule() {
    local dport=$1
    local to_ip=$2
    local to_port=$3

    iptables -t nat -D PREROUTING -p tcp --dport "$dport" -j DNAT --to-destination "${to_ip}:${to_port}" 2>/dev/null
    iptables -t nat -D POSTROUTING -d "$to_ip" -p tcp --dport "$to_port" -j MASQUERADE 2>/dev/null
    iptables -D FORWARD -p tcp -d "$to_ip" --dport "$to_port" -j ACCEPT 2>/dev/null
}

# ==================== 智能修改  ====================
modify_forward() {
    show_mapping_list
    if [ $map_count -eq 0 ]; then return; fi

    read -p "请输入要修改的规则序号: " idx
    if [ -z "${map_list[$idx]-}" ]; then
        echo -e "${RED}无效序号${NC}"
        return
    fi

    IFS='|' read -r old_port old_to_ip old_to_port <<< "${map_list[$idx]}"

    echo -e "\n${YELLOW}当前规则:$old_port → $old_to_ip:$old_to_port${NC}"

    read -p "新的目标IP [直接回车使用原IP]: " new_to_ip
    new_to_ip=${new_to_ip:-$old_to_ip}

    read -p "新的端口 [直接回车使用原端口]: " new_port
    new_port=${new_port:-$old_port}

    if ! check_ip "$new_to_ip"; then
        echo -e "${RED}IP 格式错误${NC}"
        return
    fi
    if ! check_port "$new_port"; then
        echo -e "${RED}端口格式错误${NC}"
        return
    fi

    # 删除旧的
    delete_forward_rule "$old_port" "$old_to_ip" "$old_to_port"

    # 添加新的
    enable_ip_forward
    add_forward "$new_to_ip" "$new_port"

    echo -e "${GREEN}✔ 修改完成!${NC}"
    echo -e "旧:$old_port → $old_to_ip:$old_to_port"
    echo -e "新:$new_port → $new_to_ip:$new_port"
}

menu() {
    while true; do
        clear
        echo -e "====== ${GREEN}Linux 端口映射管理脚本${NC} ======"
        echo -e "当前本机IP: ${GREEN}$(hostname -I | awk '{print $1}')${NC}"
        echo "1. 添加端口映射"
        echo "2. 删除端口映射"
        echo "3. 修改端口映射"
        echo "4. 查看当前映射列表"
        echo "5. 保存规则(重启不失效)"
        echo "0. 退出"
        echo "========================================"
        read -p "请选择操作 [0-5]: " choice

        case $choice in
            1)
                echo -e "\n${GREEN}=== 添加端口映射 ===${NC}"
                read -p "目标内网IP: " to_ip
                read -p "映射端口: " port
                if check_ip "$to_ip" && check_port "$port"; then
                    enable_ip_forward
                    add_forward "$to_ip" "$port"
                    echo -e "${GREEN}✔ 添加成功${NC}"
                    echo "映射: 本机 $port → $to_ip:$port"
                    echo "测试: nc -zv $(hostname -I | awk '{print $1}') $port"
                else
                    echo -e "${RED}IP或端口格式错误${NC}"
                fi
                ;;
            2)
                show_mapping_list
                [ $map_count -eq 0 ] && continue
                read -p "输入要删除的序号: " idx
                IFS='|' read -r dport to_ip to_port <<< "${map_list[$idx]}"
                delete_forward_rule "$dport" "$to_ip" "$to_port"
                echo -e "${GREEN}✔ 删除成功${NC}"
                ;;
            3) modify_forward ;;
            4) show_mapping_list ;;
            5)
                iptables-save > /etc/sysconfig/iptables 2>/dev/null || iptables-save >/dev/null
                echo -e "${GREEN}✔ 规则已保存,重启不失效${NC}"
                ;;
            0) echo -e "${GREEN}已退出${NC}"; exit 0 ;;
            *) echo -e "${RED}输入错误,请重试${NC}" ;;
        esac

        echo -e "\n按回车返回菜单..."
        read
    done
}

menu
posted @ 2026-03-28 14:44  xzy186  阅读(15)  评论(0)    收藏  举报