diff --git a/lib/rex/socket/comm/local.rb b/lib/rex/socket/comm/local.rb index d071eb6..60a0dfe 100644 --- a/lib/rex/socket/comm/local.rb +++ b/lib/rex/socket/comm/local.rb @@ -9,6 +9,7 @@ require 'rex/socket/sctp' require 'rex/socket/sctp_server' require 'rex/socket/ip' +require 'rex/socket/proxies' require 'timeout' ### @@ -353,7 +354,7 @@ def self.create_by_type(param, type, proto = 0) def self.proxy(sock, type, host, port) case type.downcase - when 'sapni' + when Rex::Socket::Proxies::ProxyType::SAPNI packet_type = 'NI_ROUTE' route_info_version = 2 ni_version = 39 @@ -422,7 +423,7 @@ def self.proxy(sock, type, host, port) raise Rex::ConnectionProxyError.new(host, port, type, "Connection to #{host}:#{port} failed (Unknown fail)") end - when 'http' + when Rex::Socket::Proxies::ProxyType::HTTP setup = "CONNECT #{host}:#{port} HTTP/1.0\r\n\r\n" size = sock.put(setup) if size != setup.length @@ -445,7 +446,7 @@ def self.proxy(sock, type, host, port) if resp.code != 200 raise Rex::ConnectionProxyError.new(host, port, type, "The proxy returned a non-OK response"), caller end - when 'socks4' + when Rex::Socket::Proxies::ProxyType::SOCKS4 supports_ipv6 = false setup = [4,1,port.to_i].pack('CCn') + Rex::Socket.resolv_nbo(host, supports_ipv6) + Rex::Text.rand_text_alpha(rand(8)+1) + "\x00" size = sock.put(setup) @@ -465,7 +466,7 @@ def self.proxy(sock, type, host, port) if ret[1,1] != "\x5a" raise Rex::ConnectionProxyError.new(host, port, type, "Proxy responded with error code #{ret[0,1].unpack("C")[0]}"), caller end - when 'socks5' + when Rex::Socket::Proxies::ProxyType::SOCKS5 auth_methods = [5,1,0].pack('CCC') size = sock.put(auth_methods) if size != auth_methods.length diff --git a/lib/rex/socket/parameters.rb b/lib/rex/socket/parameters.rb index 28c0004..50e749e 100644 --- a/lib/rex/socket/parameters.rb +++ b/lib/rex/socket/parameters.rb @@ -1,5 +1,6 @@ # -*- coding: binary -*- require 'rex/socket' +require 'rex/socket/proxies' ### # @@ -163,7 +164,7 @@ def initialize(hash = {}) end if hash['Proxies'] - self.proxies = hash['Proxies'].split(',').map{|a| a.strip}.map{|a| a.split(':').map{|b| b.strip}} + self.proxies = Rex::Socket::Proxies.parse(hash['Proxies']) end # The protocol this socket will be using diff --git a/lib/rex/socket/proxies.rb b/lib/rex/socket/proxies.rb new file mode 100644 index 0000000..5aa8794 --- /dev/null +++ b/lib/rex/socket/proxies.rb @@ -0,0 +1,24 @@ +# -*- coding: binary -*- + +module Rex + module Socket + module Proxies + module ProxyType + SAPNI = 'sapni' + HTTP = 'http' + SOCKS4 = 'socks4' + SOCKS5 = 'socks5' + end + + # @param [String,nil] value A proxy chain of format {type:host:port[,type:host:port][...]} + # @return [Array] The array of proxies, i.e. {[['type', 'host', 'port']]} + def self.parse(value) + value.to_s.strip.split(',').map { |a| a.strip }.map { |a| a.split(':').map { |b| b.strip } } + end + + def self.supported_types + ProxyType.constants.map { |c| ProxyType.const_get(c) } + end + end + end +end diff --git a/spec/rex/socket/proxies_spec.rb b/spec/rex/socket/proxies_spec.rb new file mode 100644 index 0000000..4405d31 --- /dev/null +++ b/spec/rex/socket/proxies_spec.rb @@ -0,0 +1,29 @@ +# -*- coding:binary -*- +require 'rex/socket/proxies' + +RSpec.describe Rex::Socket::Proxies do + describe '.supported_types' do + it 'should equal the array of available proxies' do + expected = %w[ + sapni + socks4 + http + socks5 + ] + expect(subject.supported_types).to match_array expected + end + end + + describe '.parse' do + [ + { value: nil, expected: [] }, + { value: '', expected: [] }, + { value: ' ', expected: [] }, + { value: 'sapni:198.51.100.1:8080, socks4:198.51.100.1:1080 ', expected: [['sapni', '198.51.100.1', '8080'], ['socks4', '198.51.100.1', '1080']] }, + ].each do |test| + it "correctly parses #{test[:value]} as #{test[:expected]}" do + expect(described_class.parse(test[:value])).to eq test[:expected] + end + end + end +end