decrypting SOCKS proxy

sockhole: Add option parsing to set IP, port, TLS ports, and allowed IPs

+72 -27
+72 -27
sockhole.rb
··· 23 23 require "resolv" 24 24 require "openssl" 25 25 26 - # a connection to these ports will make a TLS connection and decrypt data 27 - # before handing it back to the client 28 - TLS_PORTS = [ 29 - 443, # https 30 - 993, # imaps 31 - 995, # pop3s 32 - ] 26 + def usage 27 + STDERR.puts "usage: #{$0} [-a allowed range] [-d] [-p port] [-i ip]" 28 + exit 1 29 + end 30 + 31 + CONFIG = { 32 + # a connection to these ports will make a TLS connection and decrypt data 33 + # before handing it back to the client 34 + :tls_ports => [ 35 + 443, # https 36 + 993, # imaps 37 + 995, # pop3s 38 + ], 33 39 34 - # by default, listen on the first non-loopback IPv4 address we can find or 35 - # fallback to 127.0.0.1 36 - LISTEN_PORT = 1080 37 - LISTEN_IP = (Socket.ip_address_list.select{|a| a.ipv4? && !a.ipv4_loopback? } 38 - .map{|i| i.ip_unpack[0] }.first || "127.0.0.1") 40 + # by default, listen on the first non-loopback IPv4 address we can find or 41 + # fallback to 127.0.0.1 42 + :listen_port => 1080, 43 + :listen_ip => (Socket.ip_address_list. 44 + select{|a| a.ipv4? && !a.ipv4_loopback? }. 45 + map{|i| i.ip_unpack[0] }.first || "127.0.0.1"), 46 + 47 + :allowed_ranges => [], 48 + } 49 + 50 + while ARGV.any? 51 + case ARGV[0] 52 + when "-a" 53 + ARGV.shift 54 + begin 55 + ipr = IPAddr.new(ARGV[0]) 56 + CONFIG[:allowed_ranges].push ipr 57 + rescue IPAddr::InvalidAddressError 58 + STDERR.puts "invalid IP range #{ARGV[0]}" 59 + usage 60 + end 61 + ARGV.shift 62 + when "-d" 63 + ARGV.shift 64 + CONFIG[:debug] = true 65 + when "-p" 66 + ARGV.shift 67 + if !ARGV[0].to_s.match(/^\d+/) 68 + STDERR.puts "invalid port value" 69 + usage 70 + end 71 + CONFIG[:port] = ARGV.shift 72 + when "-i" 73 + ARGV.shift 74 + begin 75 + ip = IPAddr.new(ARGV[0]) 76 + rescue IPAddr::InvalidAddressError 77 + STDERR.puts "invalid IP #{ARGV[0]}" 78 + usage 79 + end 80 + CONFIG[:listen_ip] = ARGV.shift 81 + else 82 + usage 83 + end 84 + end 39 85 40 - # and limit connections from IPs on our local /24 network 41 - ALLOWED_IPS = [ 42 - "127.0.0.1/32", 43 - "#{LISTEN_IP}/24", 44 - ] 86 + # unless specified otherwise, allow connections from the listen ip's network 87 + if !CONFIG[:allowed_ranges].any? 88 + CONFIG[:allowed_ranges].push IPAddr.new("127.0.0.1/32") 89 + CONFIG[:allowed_ranges].push IPAddr.new("#{CONFIG[:listen_ip]}/24") 90 + end 45 91 46 92 LOGGER = Logger.new(STDOUT) 47 - if ARGV[0] == "-d" 48 - LOGGER.level = Logger::DEBUG 49 - else 50 - LOGGER.level = Logger::INFO 51 - end 93 + LOGGER.level = (CONFIG[:debug] ? Logger::DEBUG : Logger::INFO) 52 94 LOGGER.datetime_format = "%Y-%m-%d %H:%M:%S" 53 95 LOGGER.formatter = proc do |severity, datetime, progname, msg| 54 96 "[#{datetime}] [#{severity[0]}] #{msg}\n" ··· 188 230 end 189 231 190 232 def allow_connection? 191 - ALLOWED_IPS.each do |r| 192 - if IPAddr.new(r).to_range.include?(ip) 233 + CONFIG[:allowed_ranges].each do |r| 234 + if r.to_range.include?(ip) 193 235 return true 194 236 end 195 237 end ··· 198 240 end 199 241 200 242 def do_connect 201 - if TLS_PORTS.include?(remote_port) 243 + if CONFIG[:tls_ports].include?(remote_port) 202 244 @tls_decrypt = true 203 245 end 204 246 ··· 391 433 end 392 434 393 435 EM.run do 394 - EM.start_server(LISTEN_IP, LISTEN_PORT, EMSOCKS5Connection) 395 - LOGGER.info "[server] listening on #{LISTEN_IP}:#{LISTEN_PORT}" 436 + EM.start_server(CONFIG[:listen_ip], CONFIG[:listen_port], EMSOCKS5Connection) 437 + LOGGER.info "[server] listening on #{CONFIG[:listen_ip]}:" << 438 + "#{CONFIG[:listen_port]}" 439 + LOGGER.info "[server] allowing connections from " << 440 + CONFIG[:allowed_ranges].map{|i| "#{i.to_s}/#{i.prefix}" }.join(", ") 396 441 end