web-dev-qa-db-fra.com

Comment faire la redirection de port locale avec iptables

J'ai une application (serveur) à l'écoute sur le port 8080. Je veux pouvoir lui rediriger le port 80, de telle sorte que le fait de frapper http://localhost résout ma demande (le localhost:8080).

Cela devrait être généralisé pour tout mappage de port (par exemple 80:8080 => P_src:P_target), et utilisez les meilleures pratiques pour les machines modernes * nix (par exemple Ubuntu).

N.B. Tout est fait localement, il n'est donc pas nécessaire d'accepter les connexions de n'importe qui sauf localhost.

21
Murphy Danger

Donc, après de nombreuses recherches, j'ai trouvé que la réponse utilise iptables, la configuration d'un NAT et l'utilisation des fonctions PREROUTING et OUTPUT intégrées.

Tout d'abord, vous devez activer la redirection de port:

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

Ensuite, vous devez ajouter les règles suivantes à votre table iptables NAT, en utilisant vos propres valeurs pour ${P_src} et ${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}`

Si vous souhaitez supprimer les règles, il vous suffit d'utiliser le -D changer au lieu de -A pour chaque règle.

Je construis un joli petit script pour cela qui ajoute et supprime des mappages.

#!/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;
22
Murphy Danger