代码之家  ›  专栏  ›  技术社区  ›  jonathan3692bf

如何使用iptables进行本地端口转发

  •  31
  • jonathan3692bf  · 技术社区  · 10 年前

    我有一个应用程序(服务器)在端口8080上侦听。我希望能够将端口80转发到它,以便命中 http://localhost 解析我的应用程序(在 localhost:8080 ).

    对于任何端口映射(例如。 80:8080 => P_src:P_target ),并为现代*nix机器(例如Ubuntu)使用最佳实践。

    N、 B.这都是在本地完成的,因此不需要接受来自本地主机以外的任何人的连接。

    1 回复  |  直到 10 年前
        1
  •  36
  •   jonathan3692bf    9 年前

    因此,经过大量搜索,我发现答案使用iptables,设置NAT,并使用内置的PREROUTING和OUTPUT。

    首先,必须启用端口转发:

    echo "1" > /proc/sys/net/ipv4/ip_forward

    然后,您必须使用自己的值将以下规则添加到iptables NAT表中 ${P_src} ${P_target} :

    iptables -t nat -A PREROUTING -s 127.0.0.1 -p tcp --dport ${P_src} -j REDIRECT --to ${P_target}`
    iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport ${P_src} -j REDIRECT --to ${P_target}`
    

    如果要删除规则,只需使用 -D 开关而不是 -A 对于每个规则。

    我为此构建了一个很好的小脚本,用于添加和删除映射。

    #!/bin/bash
    #
    #   API: ./forwardPorts.sh add|rm p1:p1' p2:p2' ...
    #
    #   Results in the appending (-A) or deleting (-D) of iptable rule pairs that
    #   would otherwise facilitate port forwarding.
    #
    #   E.g
    #   sudo iptables -t nat -A PREROUTING -s 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to 8080
    #   sudo iptables -t nat -A OUTPUT -s 127.0.0.1 -p tcp --dport 80 -j REDIRECT --to 8080
    #
    
    if [[ $# -lt 2 ]]; then
        echo "forwardPorts takes a state (i.e. add or rm) and any number port mappings (e.g. 80:8080)";
        exit 1;
    fi
    
    case $1 in
        add )
            append_or_delete=A;;
        rm )
            append_or_delete=D;;
        * )
            echo "forwardPorts requires a state (i.e. add or rm) as it's first argument";
            exit 1; ;;
    esac
    
    shift 1;
    
    # Do a quick check to make sure all mappings are integers
    # Many thanks to S.O. for clever string splitting:
    # http://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash
    for map in "$@"
    do
        IFS=: read -a from_to_array <<< "$map"
        if  [[ ! ${from_to_array[0]} =~ ^-?[0-9]+$ ]] || [[ ! ${from_to_array[1]} =~ ^-?[0-9]+$ ]]; then
            echo "forwardPorts port maps must go from an integer, to an integer (e.g. 443:4443)";
            exit 1;
        fi
        mappings[${#mappings[@]}]=${map}
    done
    
    # We're shooting for transactional consistency. Only manipulate iptables if all 
    # the rules have a chance to succeed.
    for map in "${mappings[@]}"
    do
        IFS=: read -a from_to_array <<< "$map" 
        from=${from_to_array[0]}
        to=${from_to_array[1]}
    
        sudo iptables -t nat -$append_or_delete PREROUTING -s 127.0.0.1 -p tcp --dport $from -j REDIRECT --to $to
        sudo iptables -t nat -$append_or_delete OUTPUT -s 127.0.0.1 -p tcp --dport $from -j REDIRECT --to $to
    done
    
    exit 0;