iptables, comment redirect le port depuis loopback?

Les principales règles sont les suivantes:

OUTIF=eth0 /sbin/iptables --policy INPUT DROP /sbin/iptables --policy FORWARD DROP /sbin/iptables --policy OUTPUT ACCEPT /sbin/iptables -A INPUT -i lo -j ACCEPT /sbin/iptables -A INPUT -i $OUTIF -m state --state RELATED,ESTABLISHED -j ACCEPT 

Je veux que mysql écoute sur lo au port port 3306. Et je veux aussi qu'il écoute au port 33060 sur l'interface WAN ( eth0 ) que je veux garder à l'écart des robots.

J'ai essayé plusieurs redirections sans succès. Par exemple:

 /sbin/iptables -A INPUT -p tcp -i $OUTIF --dport 34306 -j ACCEPT /sbin/iptables -A PREROUTING -t nat -p tcp -s 0/0 --dport 34306 \ -j DNAT --to 127.0.0.1:3306 

Comment puis-je faire ceci?

ÉDITÉ:

Je vais utiliser redir cependant je veux toujours savoir comment faire avec iptables.

Celui-ci peut fonctionner, mais seulement si vous autorisez l'access au port 3306 depuis l'extérieur: ( mais cela ne fonctionne pas )

 iptables -t nat -A PREROUTING -p tcp --dport 34306 --syn -j DNAT --to :3306 

Ce que vous voulez finalement faire, c'est: ( mais cela ne fonctionne pas non plus )

 iptables -t nat -A PREROUTING -p tcp --dport 34306 --syn -j DNAT --to 127.0.0.1:3306 

C'est-à-dire que vous voulez que les packages vers le port 34306 sur une interface externe soient redirigés vers le port 3306 127.0.0.1. Cela fonctionnerait, à ceci près qu'une fois la destination réécrite à 127.0.0.1, le package devient un package martien (venant de l'extérieur avec une destination de 127.0.0.1). Les packages martiens sont filtrés normalement et silencieusement, et vous le voulez vraiment.

Il y a une solution plus giratoire impliquant des marques de pare-feu. La théorie: quand un package vient appeler le port 34306 / tcp sur votre interface externe, nous le marquons simplement comme acceptable, puis le réécrire pour qu'il apparaisse comme provenant de 3306 / tcp. Le trafic vers 3306 / tcp avec la marque est autorisé. Tout autre trafic vers 3306 / tcp est rejeté (explicitement ou implicitement, via la politique par défaut). Le code:

 IFACE=eth0 # or whatever HIPORT=34306 REALPORT=3306 MARK=42 # not-so-random random number iptables -t mangle -A PREROUTING -p tcp -i $IFACE --dport $HIPORT -j MARK --set-mark $MARK iptables -t nat -A PREROUTING -p tcp --dport $HIPORT --syn -j DNAT --to :$REALPORT iptables -A INPUT -p tcp -m mark --mark $MARK -j ACCEPT iptables -A INPUT -p tcp --dport $REALPORT -j DROP # explicitly dropping 

La dernière règle est l'endroit où vous pouvez agir sur les packages non autorisés. J'aime save tous les packages supprimés, donc mes strings tombent aux deux dernières règles, qui sont un -j LOG et -j DROP . Donc, dans mon cas, je n'en aurais pas besoin mais votre propre kilométrage variera bien sûr.

Je viens de tester cela et cela fonctionne sur mon installation. C'est un peu plus détourné que prévu, mais c'est la vie avec netfilter.

Si vous utilisez un filtrage avec état , ajoutez --syn à la règle 3 ( -m mark dans la string INPUT ) et collez-le avant les règles d'inspection de votre état. Si vous supprimez / rejetez explicitement les packages avec la règle 4 et que vous effectuez un pare-feu avec état, vous devez également append --syn à cela. C'est un tout petit peu plus compliqué (par huit octets entiers), mais les règles de vérification des marques s'appliquent uniquement au package SYN (premier) de chaque connection TCP. Une fois que la décision d'acceptation / rejet a été prise, les règles d'inspection d'état font le rest, de sorte que le pare-feu n'a pas à garder des marques de vérification pour chaque package. Aucune raison de gaspiller les cycles CPU et de maintenir les performances de votre réseau élevées.

Certaines choses à noter:

  1. Votre question mentionne le port 33060, mais votre code utilise le port 34306. J'ai utilisé ce dernier.
  2. Assurez-vous que MySQL écoute réellement 127.0.0.1:3306. Il peut utiliser un socket de domaine Unix pour les communications locales, pas un socket de domaine Internet (TCP / IP), et ce n'est pas en réseau.
  3. Vous avez seulement besoin de DNAT le package SYN . Stateful NAT traduira automatiquement tous les autres packages. Cela rend les choses légèrement plus vite.
  4. Vous n'avez pas besoin de spécifier explicitement -s 0/0, laissez simplement la source entièrement.

L'esprit de la question: la security par l'obscurité est une maîtresse dure. Vous ne vous protégez pas vraiment en changeant le port que MySQL écoute. Les scanneurs de port sont des choses automatisées, et cela ne leur pose pas de problème de scanner tous les ports d'un système. 🙂 Je vous recommand soit d'utiliser ssh avec l'option -L pour entrer de manière sécurisée, ou, si vous voulez avoir envie, un VPN. Mais parfois, la vie vous donne des citrons et vous devez faire de la limonade avec netfilter (qui est probablement l'une des rares choses que vous ne pouvez pas faire avec elle)

Jetez simplement un coup d'oeil aux outils comme nmap, considérez que les mécréants commandnt des botnets avec un time et des machines illimités et estimez combien de time "cacher MySQL sur un port (facilement devinable)" vous achètera.