Class: TransocksEM::IPFWTweaker

Inherits:
Object
  • Object
show all
Defined in:
lib/transocks_em/ipfw_tweaker.rb

Constant Summary collapse

DEFAULT_START_RULE_NUM =
1_000
OFFSET =
10
DIVERT_PORT =
4000
IPFW_SET_NUM =
7
IPFW_BIN =

Darwin & FreeBSD

'/sbin/ipfw'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ IPFWTweaker

Returns a new instance of IPFWTweaker.



14
15
16
17
18
19
20
21
22
23
24
# File 'lib/transocks_em/ipfw_tweaker.rb', line 14

def initialize(opts={})
  @start_rule_num   = opts.fetch(:start_rule_num, DEFAULT_START_RULE_NUM)
  @cur_rule_num     = @start_rule_num

  @offset           = opts.fetch(:offset, OFFSET)
  @divert_port      = opts.fetch(:divert_port, DIVERT_PORT)
  @ipfw_set_num     = opts.fetch(:ipfw_set_num, IPFW_SET_NUM)
  @added_rule_nums  = []
  @natd_pid         = nil
  @natd_config_tmpfile  = nil
end

Instance Attribute Details

#added_rule_numsObject (readonly)

Returns the value of attribute added_rule_nums.



12
13
14
# File 'lib/transocks_em/ipfw_tweaker.rb', line 12

def added_rule_nums
  @added_rule_nums
end

#divert_portObject (readonly)

Returns the value of attribute divert_port.



12
13
14
# File 'lib/transocks_em/ipfw_tweaker.rb', line 12

def divert_port
  @divert_port
end

#ipfw_set_numObject (readonly)

Returns the value of attribute ipfw_set_num.



12
13
14
# File 'lib/transocks_em/ipfw_tweaker.rb', line 12

def ipfw_set_num
  @ipfw_set_num
end

#offsetObject (readonly)

Returns the value of attribute offset.



12
13
14
# File 'lib/transocks_em/ipfw_tweaker.rb', line 12

def offset
  @offset
end

#start_rule_numObject (readonly)

Returns the value of attribute start_rule_num.



12
13
14
# File 'lib/transocks_em/ipfw_tweaker.rb', line 12

def start_rule_num
  @start_rule_num
end

Instance Method Details

#add_ipfw_diversion_rules!(ports) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/transocks_em/ipfw_tweaker.rb', line 44

def add_ipfw_diversion_rules!(ports)
  ipfw *%W[set disable #{ipfw_set_num}]
  ipfw *%W[add #{cur_rule_num} set #{ipfw_set_num} divert #{divert_port} tcp from 127.0.0.1 #{transocks_port} to me in]
  ipfw *%W[add #{cur_rule_num} set #{ipfw_set_num} divert #{divert_port} tcp from me to any #{ports.join(',')} out]
  ipfw *%W[set enable #{ipfw_set_num}]

  logger.debug do
    rules = `sudo ipfw list`
    "ipfw rules: #{rules}"
  end
end

#clear_ipfw_rules!Object



98
99
100
101
# File 'lib/transocks_em/ipfw_tweaker.rb', line 98

def clear_ipfw_rules!
  sh(*%W[sudo ipfw delete set #{ipfw_set_num}])
rescue RuntimeError
end

#clear_state!Object



39
40
41
42
# File 'lib/transocks_em/ipfw_tweaker.rb', line 39

def clear_state!
  clear_ipfw_rules!
  kill_natd!
end

#divert_to_socks(*ports) ⇒ Object

Diverts the given ports to SOCKS via ipfw and natd. after this has been called once, you must reset the rules before calling it again, or an error will occur



33
34
35
36
37
# File 'lib/transocks_em/ipfw_tweaker.rb', line 33

def divert_to_socks(*ports)
  clear_state!
  add_ipfw_diversion_rules!(ports)
  setup_natd!(ports)
end

#kill_natd!Object



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/transocks_em/ipfw_tweaker.rb', line 103

def kill_natd!
  if @natd_config_tmpfile
    @natd_config_tmpfile.close
    @natd_config_tmpfile = nil
  end

  if @natd_pid
    sh(*%W[sudo kill -9 #{@natd_pid}])
    Process.waitpid2(@natd_pid)
    @natd_pid = nil
  end
end

#setup_natd!(ports) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/transocks_em/ipfw_tweaker.rb', line 56

def setup_natd!(ports)
  kill_natd!

  @natd_config_tmpfile = tmp = Tempfile.new('natdrulez')

  tmp.puts(<<-EOS)
port #{divert_port} 
log yes
interface lo0 
proxy_only yes
  EOS

  ports.each do |port|
    tmp.puts %Q[proxy_rule type encode_tcp_stream port #{port} server 127.0.0.1:#{transocks_port}]
  end

  tmp.fsync

  tmp.rewind
  config = tmp.read

  logger.debug { "natd config: \n#{config}" }

  cmd = %W[sudo #{natd_bin} -f #{tmp.path}]

  opts = {
    :chdir => '/',
    :in  => '/dev/null',
    :out => [:child, :err],
  }

  opts[:err] = TransocksEM.debug? ? '/tmp/natd.log' : '/dev/null'

  cmd << opts

  logger.debug { "spawning natd: #{cmd.inspect}" }

  @natd_pid = Process.spawn(*cmd)

  logger.debug { "launched natd pid: #{@natd_pid}" } 
end

#transocks_portObject



26
27
28
# File 'lib/transocks_em/ipfw_tweaker.rb', line 26

def transocks_port
  TransocksEM.config[:listen_port]
end