Règle IPTables pour autoriser les connexions SSH entrantes

11

Le but de ce script est d'autoriser uniquement le trafic sur le VPN, à l'exception du localhost <-> localhost et du trafic SSH entrant. Mais lorsque j'exécute le script sur SSH, je suis déconnecté et obligé de redémarrer la VM. Quel est le problème avec mon script?

#!/bin/bash
iptables -F

#Allow over VPN
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A OUTPUT -o tun+ -j ACCEPT

#Localhost
iptables -A INPUT -s 127.0.0.1/8 -j ACCEPT
iptables -A OUTPUT -d 127.0.0.1/8 -j ACCEPT

#VPN
iptables -A INPUT -s 123.123.123.123 -j ACCEPT
iptables -A OUTPUT -d 123.123.123.123 -j ACCEPT

#SSH
iptables -A INPUT -p tcp --dport ssh -j ACCEPT

#Default Deny
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
Steven
la source

Réponses:

10

La chaîne de sortie est responsable de tout paquet sortant.

Votre script autorise uniquement les paquets sortants à tunneler l'interface, l'hôte local et l'hôte distant au 123.123.123.123.

Si vous vous connectez au serveur d'une manière qui nécessite que le démon SSH envoie des paquets vers la destination autre que l'une des précédentes, le trafic ne sera pas autorisé à sortir.

Pour autoriser les paquets sortants de votre démon SSH vers le client SSH, vous devez ajouter la règle suivante:

iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT

Vous pouvez également ajouter des critères IP de destination à la règle ci-dessus, si vous vous connectez uniquement à partir d'un seul emplacement. Cette règle doit précéder la règle ultime «DROP else else» pour la chaîne de sortie.

hellodanylo
la source
+1 Cela fonctionnera et est plus spécifique que l'utilisation d'une règle établie et connexe (ce qui la rend plus ou moins utile selon le contexte).
goldilocks
Ces deux bonnes réponses, j'ai beaucoup appris! J'ai testé la réponse @SkyDan et cela fonctionne bien!
Steven
Nitpick: la chaîne de sortie n'est pas responsable des paquets transférés .
Björn Lindqvist
13

Votre #SSHrègle implique que ssh est une forme de communication à sens unique, ce qui n'est pas le cas. Les données sont envoyées en avant et en arrière.

La manière normale de gérer cela, puisque vous ne pouvez pas connaître à l'avance le numéro de port côté client, consiste à autoriser les connexions considérées comme "établies" ou "liées" à une connexion établie. Pour ce faire, vous avez besoin de:

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Avant vos DROPrègles (et de préférence en haut, car les règles sont traitées dans l'ordre et ces deux-là s'appliqueront à la plupart des paquets).

Il y a une explication de la façon dont une connexion TCP est établie ici ; essentiellement, le fait que le serveur réponde au paquet autorisé par votre #SSH INPUTrègle le fait.

boucle d'or
la source
1
Cela ne fonctionnera pas. Établi signifie que des paquets dans les deux sens pour une connexion TCP donnée ont été vus. Si vous ajoutez uniquement cette règle, le premier paquet sortant sera toujours bloqué.
hellodanylo
2
@SkyDan Voici une référence pour cela . Notez sur le diagramme que lorsque le serveur renvoie un syn / ack au client après avoir reçu la syn d'ouverture, la connexion est établie, ce qui signifie qu'iptables laissera passer ce paquet de réponse: "Une fois qu'il a vu un paquet (le SYN), il considère la connexion comme NEW. Une fois qu'il voit le paquet de retour (SYN / ACK), il considère la connexion comme ESTABLISHED. " -> encore: iptables voit le paquet de retour que le serveur veut envoyer, établit la connexion comme établie et laisse passer la réponse.
goldilocks
1
D'accord, je vois pourquoi cela fonctionnera. C'est un peu obscur, car l'homme iptables ne parle que de voir les paquets dans les deux sens, pas un mot sur les paquets de prise de contact TCP faisant exception. Merci pour la référence!
hellodanylo
2
@SkyDan En fait, la logique ne s'applique pas uniquement à TCP - j'avais tort de -p tcpfaire une différence dans ce sens, et regardez l'explication suivante pour UDP sur cette page (c'est la même chose). Le fait est que le serveur répond sans savoir si iptables le permettra ou non, et lorsque iptables reçoit cette réponse du serveur sur le système local , il a maintenant vu du trafic dans les deux sens (même si le client ne l'a pas encore fait), considère la connexion est établie et laisse sortir la réponse. La "technicité" repose ici sur le fait que le pare-feu est au milieu des deux parties.
goldilocks
1
Vous avez raison là-bas. Quelqu'un devrait probablement inclure ces informations dans l'homme iptables.
hellodanylo