Empêcher le trafic sortant sauf si la connexion OpenVPN est active à l'aide de pf.conf sur Mac OS X

19

J'ai pu refuser toutes les connexions aux réseaux externes à moins que ma connexion OpenVPN ne soit active à l'aide de pf.conf. Cependant, je perds la connectivité Wi-Fi si la connexion est interrompue en fermant et en ouvrant le couvercle de l'ordinateur portable ou en activant et désactivant le Wi-Fi.

  • Je suis sur Mac OS 10.8.1.
  • Je me connecte au Web via le Wi-Fi (à partir de différents emplacements, y compris le Wi-Fi public).
  • La connexion OpenVPN est configurée avec Viscosity.

J'ai les règles de filtrage de paquets suivantes configurées dans /etc/pf.conf

# Deny all packets unless they pass through the OpenVPN connection
wifi=en1
vpn=tun0

block all

set skip on lo
pass on $wifi proto udp to [OpenVPN server IP address] port 443
pass on $vpn

Je démarre le service de filtrage de paquets avec sudo pfctl -eet charge les nouvelles règles avec sudo pfctl -f /etc/pf.conf.

J'ai également édité /System/Library/LaunchDaemons/com.apple.pfctl.plistet changé la ligne <string>-f</string>pour lire <string>-ef</string>afin que le filtre de paquets se lance au démarrage du système.

Tout cela semble très bien au premier abord: les applications ne peuvent se connecter au Web que si la connexion OpenVPN est active, donc je ne fuis jamais de données sur une connexion non sécurisée.

Mais, si je ferme et rouvre le couvercle de mon ordinateur portable ou si je rallume et éteint le Wi-Fi, la connexion Wi-Fi est perdue et je vois un point d'exclamation dans l'icône Wi-Fi dans la barre d'état. Un clic sur l'icône Wi-Fi affiche un message "Alerte: pas de connexion Internet":

Aucun message de connexion Internet

Pour rétablir la connexion, je dois déconnecter et reconnecter le Wi-Fi, parfois cinq ou six fois, avant que le message "Alerte: Aucune connexion Internet" ne disparaisse et que je puisse rouvrir la connexion VPN. D'autres fois, l'alerte Wi-Fi disparaît de lui-même, le point d'exclamation s'efface et je peux me reconnecter. Quoi qu'il en soit, il peut falloir cinq minutes ou plus pour rétablir une connexion, ce qui peut être frustrant.

La suppression de la ligne block allrésout le problème (mais autorise les connexions non sécurisées), il semble donc qu'il y ait un service que je bloque et dont Apple a besoin pour retrouver et confirmer une connexion Wi-Fi. J'ai essayé:

  • Activation d'icmp en ajoutant pass on $wifi proto icmp allà pf.conf
  • Activation de la résolution DNS en ajoutant pass on $wifi proto udp from $wifi to any port 53
  • Essayer d'en savoir plus en enregistrant les paquets bloqués (en changeant block allen block log all), mais la journalisation semble être désactivée sous OS X, car faire sudo tcpdump -n -e -ttt -i pflog0pour voir les résultats du journal dans "tcpdump: pflog0: Aucun périphérique de ce type n'existe".

Rien de tout cela ne permet de rétablir une connexion Wi-Fi plus rapidement.

Que puis-je faire d'autre pour déterminer quel service doit être disponible pour retrouver la connectivité Wi-Fi, ou quelle règle dois-je ajouter à pf.conf pour rendre les reconnexions Wi-Fi plus fiables?

pseudo
la source
1
cela peut être pertinent pour ceux qui viennent après: sparklabs.com/support/preventing_network_and_dns_traffic_leaks
ptim

Réponses:

14

En surveillant les connexions réseau à l'aide de Little Snitch, j'ai constaté qu'Apple utilise l'application mDNSResponder en arrière-plan pour vérifier si la connexion Wi-Fi est disponible. mDNSResponder envoie des paquets UDP aux serveurs de noms pour vérifier la connectivité et résoudre les noms d'hôte en IP.

Changer la règle UDP que j'avais précédemment pour autoriser tous les paquets UDP via Wi-Fi permet au mDNSResponder de se connecter, ce qui signifie que le Wi-Fi se reconnecte maintenant la première fois après une déconnexion. Au cas où cela aiderait les autres à l'avenir, mon pf.conf final, y compris les règles par défaut d'Apple pour Mountain Lion, ressemble à ceci:

#
# com.apple anchor point
#
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"as
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"

#
# Allow connection via Viscosity only
#
wifi=en1 #change this to en0 on MacBook Airs and other Macs without ethernet ports
vpn=tun0
vpn2=tap0

block all

set skip on lo          # allow local traffic

pass on p2p0            #allow AirDrop
pass on p2p1            #allow AirDrop
pass on p2p2            #allow AirDrop
pass quick proto tcp to any port 631    #allow AirPrint

pass on $wifi proto udp # allow only UDP packets over unprotected Wi-Fi
pass on $vpn            # allow everything else through the VPN (tun interface)
pass on $vpn2           # allow everything else through the VPN (tap interface)

Cela signifie que les données peuvent désormais être divulguées via le Wi-Fi par le petit nombre d'applications qui utilisent le protocole UDP, malheureusement, comme ntpd (pour la synchronisation de l'heure) et mDNSResponder. Mais cela semble toujours mieux que de permettre aux données de voyager sans protection via TCP, ce que la majorité des applications utilisent. Si quelqu'un a des suggestions pour améliorer cette configuration, les commentaires ou autres réponses sont les bienvenus.

pseudo
la source
C'est quelque chose qui m'intéresse avec désinvolture, voir vos résultats m'a inspiré à rentrer chez moi et à l'essayer! Merci!
jakev
@SixSlayer Cela semble assez bien fonctionner! J'ai Viscosity configuré pour se connecter automatiquement au démarrage et sur les connexions interrompues, ce qui rend le tout à peu près transparent. La principale chose à noter est que pf.conf et com.apple.pfctl.plist sont réinitialisés à leurs valeurs par défaut après les mises à jour du système d'exploitation, donc il vaut la peine de conserver une sauvegarde des deux.
Nick
À mon humble avis, la chose UDP est une sorte de déception. Je ne suis pas un gars du réseau mais ce genre de chose m'aide à apprendre, et j'ai une fascination pour avoir le contrôle sur ce genre de détails. Je vais passer un peu de temps à chercher un travail, mais si quelqu'un me bat dessus, tout aussi bien.
jakev
c'est génial - exactement ce que je cherchais. Je vous remercie!
keo
Avez-vous peut-être réussi à ouvrir de nombreuses connexions OpenVPN en même temps et à les acheminer en parallèle? (pour gagner et ajouter de la bande passante)
keo
11

Vous n'avez pas besoin d'autoriser tous les UDP. Le «m» dans mDNS signifie «multidiffusion» et il utilise une adresse IP de destination de multidiffusion spécifique appelée «adresse de multidiffusion locale de liaison» et un UDPnuméro de port 5353.

Cela signifie que dans votre solution ci-dessus, vous autorisez inutilement le trafic vers tous les ports UDP 65535 vers les 3,7 milliards d'adresses IP routables dans le monde pour contourner votre VPN. Vous seriez surpris du nombre d'applications qui utilisent UDP, vous êtes donc en train de déjouer de manière significative le but de votre idée originale d'empêcher le trafic sortant lorsque le VPN est en panne.

Pourquoi ne pas utiliser cette règle à la place:

pass on $wifi proto udp to 224.0.0.251 port 5353

Une règle d'or très importante avec la configuration du pare-feu - lorsque vous faites des exceptions via votre pare-feu, essayez toujours d'utiliser la règle la plus spécifique possible. La spécificité se fait parfois au détriment de la commodité et de la facilité d'utilisation, c'est-à-dire que vous pourriez alors trouver qu'il existe un autre protocole de liaison locale qui doit être laissé passer, et ajouter encore une autre règle spécifique.

Si vous permutez la règle ci-dessus et constatez que le problème wifi d'origine revient, alors votre PF peut bloquer DHCP, le protocole utilisé pour configurer automatiquement les adresses IP de vos périphériques réseau. (dans un réseau domestique, votre routeur à large bande serait généralement votre serveur DHCP). La règle dont vous auriez besoin pour autoriser DHCP serait:

pass on $wifi proto udp from 0.0.0.0 port 68 to 255.255.255.255 port 67

* Remarque: vous devrez peut - être remplacer 0.0.0.0par any. Le DHCPREQUESTpaquet que votre ordinateur envoie en premier a une adresse source 0.0.0.0car à ce stade, votre ordinateur n'a pas encore d'adresse IP.
Pour être honnête, je pencherais davantage pour l'utilisation any. Une autre option consiste à extraire toute spécification source, c'est-à-dire pass on $wifi proto udp to 255.255.255.255 port 67, mais cela signifie que nous perdons la partie source-port de la règle, et être aussi spécifique que possible est toujours l'option la plus sûre.

J'espère que cela pourra aider. Voici quelques liens utiles:

mDNS: http://en.wikipedia.org/wiki/Multicast_DNS#Packet_structure

DHSP: http://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol#DHCP_discovery

fracassant
la source
1

Cela m'a donné suffisamment d'informations générales pour faire le grand saut et utiliser pf.conf. Voici ce que j'utilise sur mon 10.8 pour le faire se reconnecter après la coupure de la connexion VPN:

(J'utilise uniquement Ethernet mais vous pouvez changer $ lan pour $ wifi et cela devrait fonctionner)

lan=en0
wifi=en1
vpn=tun0
block all
set skip on lo
pass on $lan proto { udp,tcp } to 8.8.8.8
pass on $lan proto tcp to vpn.btguard.com port 1194
pass on $vpn
Cédric
la source
1

Dans le but de créer les règles PF de manière "simple", en identifiant les interfaces actives existantes, y compris les interfaces actuelles (vpn), ce petit programme killswitch peut être utilisé,

Toujours en cours mais pourrait être un bon début pour identifier les IP externes et les interfaces actives afin de créer correctement les règles de pare-feu.

exemple ou sortie en utilisant l' -ioption (info):

$ killswitch -i
Interface  MAC address         IP
en1        bc:57:36:d1:82:ba   192.168.1.7
ppp0                           10.10.1.3

public IP address: 93.117.82.123

Passer l'IP du serveur -ip:

# --------------------------------------------------------------
# Sat, 19 Nov 2016 12:37:24 +0100
# sudo pfctl -Fa -f ~/.killswitch.pf.conf -e
# --------------------------------------------------------------
int_en1 = "en1"
vpn_ppp0 = "ppp0"
vpn_ip = "93.117.82.123"
set block-policy drop
set ruleset-optimization basic
set skip on lo0
block all
pass on $int_en1 proto udp to 224.0.0.251 port 5353
pass on $int_en1 proto udp from any port 67 to any port 68
pass on $int_en1 inet proto icmp all icmp-type 8 code 0
pass on $int_en1 proto {tcp, udp} from any to $vpn_ip
pass on $vpn_ppp0 all

Est loin d'être parfait mais le travail est en cours plus d'informations / code peuvent être trouvés ici: https://github.com/vpn-kill-switch/killswitch

nbari
la source
0

- En complément -

Vous voudrez peut-être ajouter cette ligne:

pass on $wifi inet6 proto udp from any to FF02:0000:0000:0000:0000:0000:0000:00FB port 5353

pour permettre à mDNS de fonctionner sur ipv6

user263367
la source