10
10
from helpers import log , debug1 , debug3 , islocal , Fatal , family_to_string , \
11
11
resolvconf_nameservers
12
12
from fcntl import ioctl
13
- from ctypes import c_char , c_uint8 , c_uint16 , c_uint32 , Union , Structure , sizeof , addressof , memmove
13
+ from ctypes import c_char , c_uint8 , c_uint16 , c_uint32 , Union , Structure , \
14
+ sizeof , addressof , memmove
14
15
15
16
16
17
# python doesn't have a definition for this
@@ -466,23 +467,28 @@ def do_wait():
466
467
return do_wait
467
468
468
469
469
- def pfctl (* args ):
470
- argv = ['pfctl' ] + list (args )
471
- debug1 ('>> %s\n ' % ' ' .join (argv ))
472
- rv = ssubprocess .Popen (argv , stderr = ssubprocess .PIPE ).wait ()
473
- if rv :
474
- raise Fatal ('%r returned %d' % (argv , rv ))
470
+ def pfctl (args , stdin = None ):
471
+ argv = ['pfctl' ] + list (args .split (" " ))
472
+ debug1 ('>> %s, stdin:%s\n ' % (' ' .join (argv ), stdin ))
473
+
474
+ p = ssubprocess .Popen (argv , stdin = ssubprocess .PIPE ,
475
+ stdout = ssubprocess .PIPE ,
476
+ stderr = ssubprocess .PIPE )
477
+ o = p .communicate (stdin )
478
+ if p .returncode :
479
+ raise Fatal ('%r returned %d' % (argv , p .returncode ))
475
480
481
+ return o
482
+
483
+ _pf_started_by_sshuttle = False
476
484
477
485
def do_pf (port , dnsport , family , subnets , udp ):
486
+ global _pf_started_by_sshuttle
478
487
tables = []
479
488
translating_rules = []
480
489
filtering_rules = []
481
490
482
491
if subnets :
483
- pf_add_anchor_rule (PF_PASS , "sshuttle" )
484
- pf_add_anchor_rule (PF_RDR , "sshuttle" )
485
-
486
492
include_subnets = filter (lambda s :not s [2 ], sorted (subnets , reverse = True ))
487
493
if include_subnets :
488
494
tables .append ('table <include_subnets> {%s}' % ',' .join (["%s/%s" % (n [3 ], n [1 ]) for n in include_subnets ]))
@@ -500,13 +506,23 @@ def do_pf(port, dnsport, family, subnets, udp):
500
506
translating_rules .append ('rdr pass on lo0 proto udp to <dns_servers> port 53 -> 127.0.0.1 port %r' % dnsport )
501
507
filtering_rules .append ('pass out route-to lo0 inet proto udp to <dns_servers> port 53 keep state' )
502
508
503
- pf_config_file = '/etc/pf-sshuttle.conf'
504
- with open (pf_config_file , 'w+' ) as f :
505
- f .write ('\n ' .join (tables + translating_rules + filtering_rules ) + '\n ' )
509
+ rules = '\n ' .join (tables + translating_rules + filtering_rules ) + '\n '
506
510
507
- pfctl ('-E' , '-a' , 'sshuttle' , '-f' , pf_config_file )
511
+ pf_status = pfctl ('-s all' )[0 ]
512
+ if not '\n rdr-anchor "sshuttle" all\n ' in pf_status :
513
+ pf_add_anchor_rule (PF_RDR , "sshuttle" )
514
+ if not '\n anchor "sshuttle" all\n ' in pf_status :
515
+ pf_add_anchor_rule (PF_PASS , "sshuttle" )
516
+ if not 'INFO:\n Status: Enabled' in pf_status :
517
+ pfctl ('-e' )
518
+ _pf_started_by_sshuttle = True
519
+
520
+ pfctl ('-a sshuttle -f /dev/stdin' , rules )
508
521
else :
509
- pfctl ('-a' , 'sshuttle' , '-F' , 'all' )
522
+ pfctl ('-a sshuttle -F all' )
523
+
524
+ if _pf_started_by_sshuttle :
525
+ pfctl ('-d' )
510
526
511
527
512
528
def program_exists (name ):
0 commit comments