Impedisci il traffico in uscita a meno che la connessione OpenVPN sia attiva utilizzando pf.conf su Mac OS X


19

Sono stato in grado di negare tutte le connessioni a reti esterne a meno che la mia connessione OpenVPN non sia attiva utilizzando pf.conf. Tuttavia, perdo la connettività Wi-Fi se la connessione viene interrotta chiudendo e aprendo il coperchio del laptop o disattivando e riaccendendo il Wi-Fi.

  • Sono su Mac OS 10.8.1.
  • Mi collego al Web tramite Wi-Fi (da varie posizioni, incluso il Wi-Fi pubblico).
  • La connessione OpenVPN è impostata con Viscosità.

Ho impostato le seguenti regole di filtro pacchetti /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

Inizio il servizio di filtro pacchetti con sudo pfctl -ee carico le nuove regole sudo pfctl -f /etc/pf.conf.

Ho anche modificato /System/Library/LaunchDaemons/com.apple.pfctl.pliste modificato la riga <string>-f</string>in <string>-ef</string>modo che il filtro pacchetti venga avviato all'avvio del sistema.

Tutto sembra funzionare benissimo all'inizio: le applicazioni possono connettersi al Web solo se la connessione OpenVPN è attiva, quindi non sto mai perdendo dati su una connessione non sicura.

Ma, se chiudo e riapro il coperchio del laptop o spengo e riaccendo il Wi-Fi, la connessione Wi-Fi viene persa e vedo un punto esclamativo nell'icona Wi-Fi nella barra di stato. Facendo clic sull'icona Wi-Fi viene visualizzato il messaggio "Avviso: nessuna connessione a Internet":

Nessun messaggio di connessione a Internet

Per riottenere la connessione, devo disconnettere e riconnettere il Wi-Fi, a volte cinque o sei volte, prima che scompaia il messaggio "Avviso: Nessuna connessione a Internet" e posso riaprire la connessione VPN. Altre volte, l'avviso Wi-Fi scompare da solo, il punto esclamativo si cancella e sono in grado di riconnettermi. In entrambi i casi, possono essere necessari cinque minuti o più per ottenere nuovamente una connessione, il che può essere frustrante.

La rimozione della linea block allrisolve il problema (ma consente connessioni non sicure), quindi sembra che ci sia un servizio che sto bloccando che Apple richiede per riconquistare e confermare una connessione Wi-Fi. Ho provato:

  • Abilitare icmp aggiungendo pass on $wifi proto icmp alla pf.conf
  • Abilitazione della risoluzione DNS aggiungendo pass on $wifi proto udp from $wifi to any port 53
  • Sto cercando di saperne di più registrando i pacchetti bloccati (cambiando block allin block log all), ma la registrazione sembra essere disabilitata in OS X, perché facendo sudo tcpdump -n -e -ttt -i pflog0vedere i risultati del registro in "tcpdump: pflog0: non esiste un tale dispositivo".

Niente di tutto ciò aiuta a ristabilire una connessione Wi-Fi più velocemente.

Cos'altro posso fare per determinare quale servizio deve essere disponibile per riottenere la connettività Wi-Fi o quale regola devo aggiungere a pf.conf per rendere più affidabili le riconnessioni Wi-Fi?


1
questo può essere rilevante per coloro che verranno
ptim

Risposte:


14

Monitorando le connessioni di rete utilizzando Little Snitch, ho scoperto che Apple utilizza l'app mDNSResponder in background per verificare se la connessione Wi-Fi è disponibile. mDNSResponder invia i pacchetti UDP ai nameserver per verificare la connettività e risolvere i nomi host su IP.

La modifica della regola UDP che avevo in precedenza per consentire tutti i pacchetti UDP su Wi-Fi consente a mDNSResponder di connettersi, il che significa che il Wi-Fi ora si riconnette per la prima volta dopo una disconnessione. Nel caso in cui aiuti altri in futuro, il mio pf.conf finale, incluse le regole predefinite di Apple per Mountain Lion, è simile al seguente:

#
# 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)

Ciò significa che i dati possono ora essere trapelati tramite Wi-Fi dal piccolo numero di applicazioni che utilizzano il protocollo UDP, sfortunatamente, come ntpd (per la sincronizzazione oraria) e mDNSResponder. Ma questo sembra ancora meglio che consentire ai dati di viaggiare non protetti su TCP, che è ciò che utilizza la maggior parte delle applicazioni. Se qualcuno ha qualche suggerimento da migliorare su questa configurazione, commenti o ulteriori risposte sono i benvenuti.


Questo è qualcosa che mi è casualmente interessato, vedere i tuoi risultati mi ha ispirato ad andare a casa e provarlo! Grazie!
Jakev,

@SixSlayer Sembra funzionare abbastanza bene! Ho Viscosity impostato per connettersi automaticamente all'avvio e su connessioni interrotte, il che rende il tutto praticamente senza soluzione di continuità. La cosa principale da notare è che pf.conf e com.apple.pfctl.plist vengono ripristinati ai valori predefiniti dopo gli aggiornamenti del sistema operativo, a quanto pare, quindi vale la pena conservare un backup di entrambi.
Nick,

IMHO la cosa UDP è un po 'un peccato. Non sono un ragazzo di rete, ma questo genere di cose mi aiuta a imparare e ho il fascino di avere il controllo su questo tipo di dettagli. Trascorrerò un po 'di tempo a cercare un lavoro in giro, ma se qualcuno mi picchia ad esso, altrettanto bene.
Jakev,

è fantastico, esattamente quello che stavo cercando. Grazie!
keo,

Sei forse riuscito ad aprire molte connessioni OpenVPN contemporaneamente e instradarle in parallelo? (per guadagnare e sommare la larghezza di banda)
keo

11

Non è necessario consentire tutto l' UDP. La "m" in mDNS significa "multicast" e utilizza un indirizzo IP di destinazione multicast specifico chiamato "collegamento indirizzo multicast locale" e un UDPnumero di porta 5353.

Ciò significa che nella soluzione sopra indicata, si consente inutilmente il traffico a tutte le 65535 porte UDP a tutti i 3,7 miliardi di indirizzi IP instradabili nel mondo per bypassare la VPN. Sareste sorpresi dal numero di applicazioni che utilizzano UDP, quindi state notevolmente vanificando lo scopo dell'idea originale per impedire il traffico in uscita quando la VPN è inattiva.

Perché non usare questa regola invece:

pass on $wifi proto udp to 224.0.0.251 port 5353

Una regola empirica molto importante con la configurazione del firewall: quando si fanno eccezioni attraverso il firewall, provare sempre a utilizzare la regola più specifica possibile. La specificità a volte viene a scapito della convenienza e della facilità d'uso, ad esempio potresti scoprire che c'è qualche altro protocollo link-local che deve essere lasciato passare e aggiungere ancora un'altra regola specifica.

Se si scambia la regola sopra e si rileva che il problema wifi originale ritorna, il PF potrebbe bloccare il DHCP, il protocollo utilizzato per configurare automaticamente gli indirizzi IP dei dispositivi di rete. (in una rete domestica, in genere il router a banda larga sarebbe il server DHCP). La regola che dovresti consentire al DHCP sarebbe:

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

* Nota: potrebbe essere necessario sostituire 0.0.0.0per any. Il DHCPREQUESTpacchetto che il tuo computer invia per primo, ha un indirizzo di origine 0.0.0.0perché in quella fase il tuo computer non ha ancora un indirizzo IP.
Ad essere sincero, mi affiderei maggiormente all'utilizzo any. Un'altra opzione è quella di strappare qualsiasi specifica di origine, ovvero pass on $wifi proto udp to 255.255.255.255 port 67, ma ciò significa che perdiamo la parte della porta di origine della regola ed essere il più specifico possibile è sempre l'opzione più sicura.

Spero che aiuti. Ecco alcuni link utili:

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

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


1

Questo mi ha dato informazioni di base sufficienti per fare il grande salto e usare pf.conf. Ecco cosa uso sul mio 10.8 per farlo riconnettere dopo che la connessione VPN si interrompe:

(Uso solo ethernet ma puoi cambiare $ lan per $ wifi e dovrebbe funzionare)

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

1

Con l'obiettivo di creare le regole PF in modo "semplice", identificando le interfacce attive esistenti, comprese le interfacce attuali (vpn), è possibile utilizzare questo piccolo programma Killswitch ,

Ancora in corso, ma potrebbe essere un buon inizio per identificare l'IP esterno e le interfacce attive per creare correttamente le regole del firewall.

esempio o output usando l' -iopzione (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

Passando l'ip del server -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

È tutt'altro che perfetto ma i lavori sono in corso ulteriori informazioni / codice sono disponibili qui: https://github.com/vpn-kill-switch/killswitch


0

- Come aggiunta -

Potresti voler aggiungere questa riga:

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

per consentire a mDNS di funzionare su ipv6

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.