anytls 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +11 -0
  3. data/LICENSE +21 -0
  4. data/README.md +143 -0
  5. data/bin/anytls-client +7 -0
  6. data/bin/anytls-server +7 -0
  7. data/docs/ARCHITECTURE.md +105 -0
  8. data/docs/SOURCES.md +15 -0
  9. data/docs/VALIDATION.md +100 -0
  10. data/docs/validation/runtime-ruby34.json +8 -0
  11. data/docs/validation/runtime-ruby40.json +8 -0
  12. data/docs/validation/stress-c1.json +25 -0
  13. data/docs/validation/stress-c128.json +26 -0
  14. data/docs/validation/stress-c32.json +26 -0
  15. data/docs/validation/stress-sequential-10000.json +26 -0
  16. data/lib/anytls/address.rb +53 -0
  17. data/lib/anytls/buffered_io.rb +185 -0
  18. data/lib/anytls/byte_buffer.rb +61 -0
  19. data/lib/anytls/cli/client_listener.rb +91 -0
  20. data/lib/anytls/cli/options.rb +160 -0
  21. data/lib/anytls/cli/runner.rb +89 -0
  22. data/lib/anytls/cli/shutdown.rb +36 -0
  23. data/lib/anytls/client.rb +129 -0
  24. data/lib/anytls/connection_uri.rb +96 -0
  25. data/lib/anytls/deadline.rb +34 -0
  26. data/lib/anytls/dialer.rb +70 -0
  27. data/lib/anytls/errors.rb +23 -0
  28. data/lib/anytls/inbound/http_proxy.rb +224 -0
  29. data/lib/anytls/inbound/mixed.rb +60 -0
  30. data/lib/anytls/inbound/socks4.rb +55 -0
  31. data/lib/anytls/inbound/socks5.rb +138 -0
  32. data/lib/anytls/io_helpers.rb +87 -0
  33. data/lib/anytls/log.rb +15 -0
  34. data/lib/anytls/padding/scheme.rb +121 -0
  35. data/lib/anytls/padding/writer.rb +55 -0
  36. data/lib/anytls/protocol/authentication.rb +44 -0
  37. data/lib/anytls/protocol/decoder.rb +39 -0
  38. data/lib/anytls/protocol/frame.rb +40 -0
  39. data/lib/anytls/protocol/settings.rb +53 -0
  40. data/lib/anytls/protocol/socks_address.rb +59 -0
  41. data/lib/anytls/relay.rb +49 -0
  42. data/lib/anytls/server.rb +220 -0
  43. data/lib/anytls/session.rb +593 -0
  44. data/lib/anytls/session_pool.rb +166 -0
  45. data/lib/anytls/stream.rb +151 -0
  46. data/lib/anytls/tls_config.rb +76 -0
  47. data/lib/anytls/transport/tls_connection.rb +117 -0
  48. data/lib/anytls/uot/connection.rb +122 -0
  49. data/lib/anytls/uot/server.rb +97 -0
  50. data/lib/anytls/version.rb +6 -0
  51. data/lib/anytls.rb +40 -0
  52. metadata +203 -0
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
4
+
5
+ module AnyTLS
6
+ module UoT
7
+ # 按地址族延迟创建 UDP socket,为一条 UoT 流转发数据包。
8
+ # 固定目标在报告就绪前完成解析和 socket 连接;handle 持有全部线程
9
+ # 及 socket,任一转发方向结束时统一清理。
10
+ class Server
11
+ def initialize(logger: nil)
12
+ @logger = logger
13
+ end
14
+
15
+ def handle(stream, on_ready: nil, on_failure: nil)
16
+ ready_reported = false
17
+ connection = Connection.accept(stream, timeout: 5)
18
+ connected_address = resolve(connection.destination) if connection.destination
19
+ sockets = {}
20
+ lock = Mutex.new
21
+ finished = Queue.new
22
+ workers = []
23
+ stopping = false
24
+ create_socket = lambda do |family|
25
+ lock.synchronize do
26
+ raise ClosedError, "UDP relay closed" if stopping
27
+
28
+ sockets[family] ||= begin
29
+ socket = UDPSocket.new(family)
30
+ socket.bind(family == Socket::AF_INET6 ? "::" : "0.0.0.0", 0)
31
+ if connected_address
32
+ socket.connect(connected_address.ip_address,
33
+ connected_address.ip_port)
34
+ end
35
+ workers << Thread.new do
36
+ loop do
37
+ payload, sender = socket.recvfrom(Connection::MAX_PACKET_SIZE + 1)
38
+ address = connection.destination || Address.new(host: sender[3], port: sender[1])
39
+ connection.send_packet(payload, destination: address)
40
+ end
41
+ rescue IOError, SystemCallError, Error => error
42
+ finished << error
43
+ end
44
+ socket
45
+ rescue StandardError
46
+ socket&.close unless socket&.closed?
47
+ raise
48
+ end
49
+ end
50
+ end
51
+ # 确认流连接成功前,先建立真实出站 socket。
52
+ create_socket.call(connected_address ? connected_address.afamily : Socket::AF_INET)
53
+ on_ready&.call
54
+ ready_reported = true
55
+ workers << Thread.new do
56
+ loop do
57
+ payload, destination = connection.receive_packet
58
+ address = connected_address || resolve(destination)
59
+ socket = create_socket.call(address.afamily)
60
+ connected_address ? socket.send(payload, 0) : socket.send(payload, 0, address.to_sockaddr)
61
+ end
62
+ rescue IOError, SystemCallError, Error, SocketError => error
63
+ finished << error
64
+ end
65
+ finished.pop
66
+ nil
67
+ rescue StandardError => error
68
+ unless ready_reported
69
+ begin
70
+ on_failure&.call(error)
71
+ rescue StandardError
72
+ # 通知失败不能替换原始出站异常。
73
+ nil
74
+ end
75
+ end
76
+ raise
77
+ ensure
78
+ lock&.synchronize do
79
+ stopping = true
80
+ sockets&.each_value(&:close)
81
+ end
82
+ IOHelpers.close(stream)
83
+ workers&.each(&:join)
84
+ end
85
+
86
+ private
87
+
88
+ def resolve(destination)
89
+ raise ProtocolError, "UDP destination port must be positive" unless destination.port.positive?
90
+
91
+ Addrinfo.getaddrinfo(destination.host, destination.port, nil, :DGRAM, timeout: 5).first
92
+ rescue IO::TimeoutError, Errno::ETIMEDOUT => error
93
+ raise TimeoutError, "UDP destination resolution timed out", cause: error
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnyTLS
4
+ # gemspec、命令行和对端标识共用的唯一版本来源。
5
+ VERSION = "0.1.0"
6
+ end
data/lib/anytls.rb ADDED
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ # 显式加载入口;加载 gem 本身不启动监听器或会话。
4
+ # Client 首次连接和 Server#run 启动各自的业务 I/O。
5
+ require "socket"
6
+ require "openssl"
7
+ require "digest"
8
+ require "ipaddr"
9
+ require "securerandom"
10
+ require "stringio"
11
+ require "logger"
12
+
13
+ require_relative "anytls/version"
14
+ require_relative "anytls/errors"
15
+ require_relative "anytls/log"
16
+ require_relative "anytls/deadline"
17
+ require_relative "anytls/io_helpers"
18
+ require_relative "anytls/address"
19
+ require_relative "anytls/connection_uri"
20
+ require_relative "anytls/protocol/frame"
21
+ require_relative "anytls/protocol/decoder"
22
+ require_relative "anytls/protocol/settings"
23
+ require_relative "anytls/protocol/socks_address"
24
+ require_relative "anytls/protocol/authentication"
25
+ require_relative "anytls/padding/scheme"
26
+ require_relative "anytls/padding/writer"
27
+ require_relative "anytls/tls_config"
28
+ require_relative "anytls/dialer"
29
+ require_relative "anytls/transport/tls_connection"
30
+ require_relative "anytls/byte_buffer"
31
+ require_relative "anytls/stream"
32
+ require_relative "anytls/session"
33
+ require_relative "anytls/session_pool"
34
+ require_relative "anytls/client"
35
+ require_relative "anytls/server"
36
+ require_relative "anytls/buffered_io"
37
+ require_relative "anytls/relay"
38
+ require_relative "anytls/uot/connection"
39
+ require_relative "anytls/uot/server"
40
+ require_relative "anytls/inbound/mixed"
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: anytls
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - AnyTLS Ruby contributors
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: ipaddr
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.2'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.2'
26
+ - !ruby/object:Gem::Dependency
27
+ name: logger
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.6'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '2'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '1.6'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '2'
46
+ - !ruby/object:Gem::Dependency
47
+ name: openssl
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '3.3'
53
+ - - "<"
54
+ - !ruby/object:Gem::Version
55
+ version: '5'
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '3.3'
63
+ - - "<"
64
+ - !ruby/object:Gem::Version
65
+ version: '5'
66
+ - !ruby/object:Gem::Dependency
67
+ name: protocol-http1
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - "~>"
71
+ - !ruby/object:Gem::Version
72
+ version: 0.41.0
73
+ type: :runtime
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: 0.41.0
80
+ - !ruby/object:Gem::Dependency
81
+ name: securerandom
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0.3'
87
+ - - "<"
88
+ - !ruby/object:Gem::Version
89
+ version: '1'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0.3'
97
+ - - "<"
98
+ - !ruby/object:Gem::Version
99
+ version: '1'
100
+ - !ruby/object:Gem::Dependency
101
+ name: uri
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '1.0'
107
+ - - "<"
108
+ - !ruby/object:Gem::Version
109
+ version: '2'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '1.0'
117
+ - - "<"
118
+ - !ruby/object:Gem::Version
119
+ version: '2'
120
+ description: A Ruby implementation of the AnyTLS protocol, with TCP, UDP-over-TCP
121
+ and mixed proxy listeners.
122
+ executables:
123
+ - anytls-client
124
+ - anytls-server
125
+ extensions: []
126
+ extra_rdoc_files: []
127
+ files:
128
+ - CHANGELOG.md
129
+ - LICENSE
130
+ - README.md
131
+ - bin/anytls-client
132
+ - bin/anytls-server
133
+ - docs/ARCHITECTURE.md
134
+ - docs/SOURCES.md
135
+ - docs/VALIDATION.md
136
+ - docs/validation/runtime-ruby34.json
137
+ - docs/validation/runtime-ruby40.json
138
+ - docs/validation/stress-c1.json
139
+ - docs/validation/stress-c128.json
140
+ - docs/validation/stress-c32.json
141
+ - docs/validation/stress-sequential-10000.json
142
+ - lib/anytls.rb
143
+ - lib/anytls/address.rb
144
+ - lib/anytls/buffered_io.rb
145
+ - lib/anytls/byte_buffer.rb
146
+ - lib/anytls/cli/client_listener.rb
147
+ - lib/anytls/cli/options.rb
148
+ - lib/anytls/cli/runner.rb
149
+ - lib/anytls/cli/shutdown.rb
150
+ - lib/anytls/client.rb
151
+ - lib/anytls/connection_uri.rb
152
+ - lib/anytls/deadline.rb
153
+ - lib/anytls/dialer.rb
154
+ - lib/anytls/errors.rb
155
+ - lib/anytls/inbound/http_proxy.rb
156
+ - lib/anytls/inbound/mixed.rb
157
+ - lib/anytls/inbound/socks4.rb
158
+ - lib/anytls/inbound/socks5.rb
159
+ - lib/anytls/io_helpers.rb
160
+ - lib/anytls/log.rb
161
+ - lib/anytls/padding/scheme.rb
162
+ - lib/anytls/padding/writer.rb
163
+ - lib/anytls/protocol/authentication.rb
164
+ - lib/anytls/protocol/decoder.rb
165
+ - lib/anytls/protocol/frame.rb
166
+ - lib/anytls/protocol/settings.rb
167
+ - lib/anytls/protocol/socks_address.rb
168
+ - lib/anytls/relay.rb
169
+ - lib/anytls/server.rb
170
+ - lib/anytls/session.rb
171
+ - lib/anytls/session_pool.rb
172
+ - lib/anytls/stream.rb
173
+ - lib/anytls/tls_config.rb
174
+ - lib/anytls/transport/tls_connection.rb
175
+ - lib/anytls/uot/connection.rb
176
+ - lib/anytls/uot/server.rb
177
+ - lib/anytls/version.rb
178
+ homepage: https://github.com/gatework/anytls
179
+ licenses:
180
+ - MIT
181
+ metadata:
182
+ rubygems_mfa_required: 'true'
183
+ source_code_uri: https://github.com/gatework/anytls
184
+ changelog_uri: https://github.com/gatework/anytls/blob/main/CHANGELOG.md
185
+ bug_tracker_uri: https://github.com/gatework/anytls/issues
186
+ rdoc_options: []
187
+ require_paths:
188
+ - lib
189
+ required_ruby_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '3.4'
194
+ required_rubygems_version: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">="
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
+ requirements: []
200
+ rubygems_version: 4.0.20
201
+ specification_version: 4
202
+ summary: AnyTLS client and server for Ruby
203
+ test_files: []