Class: ShadowsocksRuby::Protocols::Socks5Protocol

Inherits:
Object
  • Object
show all
Includes:
DummyHelper
Defined in:
lib/shadowsocks_ruby/protocols/packet/socks5.rb

Overview

Note:

Now only implemented the server side protocol, not the client side protocol.

SOCKS 5 protocol

specification :

Constant Summary collapse

METHOD_NO_AUTH =
0
CMD_CONNECT =
1
REP_SUCCESS =
0
RESERVED =
0
ATYP_IPV4 =
1
ATYP_DOMAIN =
3
ATYP_IPV6 =
4
SOCKS5 =
5

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DummyHelper

#async_recv, #raise_me, #send_data

Constructor Details

#initialize(params = {}) ⇒ Socks5Protocol

Returns a new instance of Socks5Protocol.

Parameters:

  • params (Hash) (defaults to: {})

    Configuration parameters



26
27
28
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 26

def initialize params = {}
  @params = {}.merge(params)
end

Instance Attribute Details

#next_protocolObject

Returns the value of attribute next_protocol.



14
15
16
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 14

def next_protocol
  @next_protocol
end

Instance Method Details

#tcp_receive_from_client_first_packet(n) ⇒ Object Also known as: tcp_receive_from_client



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 30

def tcp_receive_from_client_first_packet n
  # check version
  version = async_recv(1).unpack("C").first
  if version != SOCKS5
    raise PharseError, "SOCKS version not supported: #{version.inspect}"
  end

  # client handshake v5
  nmethods = async_recv(1).unpack("C").first
  *methods = async_recv(nmethods).unpack("C*")
  if methods.include?(METHOD_NO_AUTH)
    packet = [SOCKS5, METHOD_NO_AUTH].pack("C*")
    send_data packet
  else
    raise PharseError, 'Unsupported authentication method. Only "No Authentication" is supported'
  end

  version, command, reserved = async_recv(3).unpack("C3")
  buf =''
  buf << (s = async_recv(1))
  address_type = s.unpack("C").first
  case address_type
  when ATYP_IPV4
    buf << async_recv(4)
  when ATYP_IPV6
    buf << async_recv(16)
  when ATYP_DOMAIN
    buf << (s = async_recv(1))
    domain_len = s.unpack("C").first
    buf << async_recv(domain_len)
    buf << async_recv(2) # port
  else
    raise PharseError, "unknown address_type: #{address_type}"
  end 

  packet = ([SOCKS5, REP_SUCCESS, RESERVED, 1, 0, 0, 0, 0, 0]).pack("C8n")
  send_data packet
  class << self
    alias tcp_receive_from_client tcp_receive_from_client_other_packet
  end

  # first packet is special:
  # ATYP + Destination Address + Destination Port
  buf        
end

#tcp_receive_from_client_other_packet(n) ⇒ Object



78
79
80
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 78

def tcp_receive_from_client_other_packet n
  async_recv(n)
end

#tcp_receive_from_localbackend_first_packet(n) ⇒ Object Also known as: tcp_receive_from_localbackend



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 86

def tcp_receive_from_localbackend_first_packet n
  # check version
  version = async_recv(1).unpack("C").first
  if version != SOCKS5
    raise PharseError, "SOCKS version not supported: #{version.inspect}"
  end

  # client handshake v5
  nmethods = async_recv(1).unpack("C").first
  *methods = async_recv(nmethods).unpack("C*")
  if methods.include?(METHOD_NO_AUTH)
    packet = [SOCKS5, METHOD_NO_AUTH].pack("C*")
    send_data packet
  else
    raise PharseError, 'Unsupported authentication method. Only "No Authentication" is supported'
  end

  version, command, reserved = async_recv(3).unpack("C3")
  buf =''
  buf << (s = async_recv(1))
  address_type = s.unpack("C").first
  case address_type
  when ATYP_IPV4
    buf << async_recv(4)
  when ATYP_IPV6
    buf << async_recv(16)
  when ATYP_DOMAIN
    buf << (s = async_recv(1))
    domain_len = s.unpack("C").first
    buf << async_recv(domain_len)
    buf << async_recv(2) # port
  else
    raise PharseError, "unknown address_type: #{address_type}"
  end

  packet = ([SOCKS5, REP_SUCCESS, RESERVED, 1, 0, 0, 0, 0, 0]).pack("C8n")
  send_data packet

  class << self
    alias tcp_receive_from_localbackend tcp_receive_from_localbackend_other_packet
  end

  # first packet is special:
  # ATYP + Destination Address + Destination Port
  buf                
end

#tcp_receive_from_localbackend_other_packet(n) ⇒ Object



135
136
137
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 135

def tcp_receive_from_localbackend_other_packet n
  async_recv(n)
end

#tcp_send_to_client(data) ⇒ Object



82
83
84
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 82

def tcp_send_to_client data
  send_data data
end

#tcp_send_to_localbackend(data) ⇒ Object



139
140
141
# File 'lib/shadowsocks_ruby/protocols/packet/socks5.rb', line 139

def tcp_send_to_localbackend data
  send_data data
end