- I saw some designs, But it is not ideal / meets the requirements.
- After a day of conception / thinking, a day of design / debugging,
Herbal.cr
has been initially completed.- I reference to RFC1928 and some guidelines for design, actually SOCKS5 is not difficult.
- Third-party guides are more effective and practical, and has been verified by Wireshark test.
- Due to time constraints, Travis-CI and Spec tests have not been added for the time being.
- While designing, I drew RFC1928 as a drawing, That's why I did it quickly, (I put in the root directory).
- It can proxy TCP traffic as well as UDP traffic.
- TCPConnection
- TCPBinding
- AssociateUDP
- It is a full-featured SOCKS5 Client / Server.
- SimpleAuth (Does not support GSSAPI)
- Local DNS resolution / Remote DNS resolution
- TCPConnection / TCPBinding / AssociateUDP
- Reject Establish (Server)
- Plugin (Fuzzy Wrapper)
- HTTP / 1.1 KeepAlive Wrapper
- WebSocket Wrapper
- Loosely coupled, Low footprint, High performance.
- ...
- Does not support Generic Security Services Application Program Interface authentication.
- Does not support SOCKS4 and SOCKS4A Protocols.
- Simple Client
require "herbal"
# Durian
dns_servers = [] of Durian::Resolver::Server
dns_servers << Durian::Resolver::Server.new ipAddress: Socket::IPAddress.new("8.8.8.8", 53_i32), protocol: Durian::Protocol::UDP
dns_servers << Durian::Resolver::Server.new ipAddress: Socket::IPAddress.new("1.1.1.1", 53_i32), protocol: Durian::Protocol::UDP
dns_resolver = Durian::Resolver.new dns_servers
resolver.ip_cache = Durian::Cache::IPAddress.new
# Herbal
begin
client = Herbal::Client.new "0.0.0.0", 1234_i32, dns_resolver
# Authentication (Optional)
# client.authentication_methods = [Herbal::Authentication::NoAuthentication, Herbal::Authentication::UserNamePassword]
# client.on_auth = Herbal::AuthenticationEntry.new "admin", "abc123"
client.connect! "www.example.com", 80_i32, Herbal::Command::TCPConnection, remote_resolution: true
# Write Payload
memory = IO::Memory.new
request = HTTP::Request.new "GET", "http://www.example.com"
request.to_io memory
client.write memory.to_slice
# _Read Payload
buffer = uninitialized UInt8[4096_i32]
length = client.read buffer.to_slice
STDOUT.puts [:length, length]
STDOUT.puts String.new buffer.to_slice[0_i32, length]
rescue ex
STDOUT.puts [ex]
end
client.try &.close
- Simple Server
require "herbal"
def handle_client(context : Herbal::Context)
STDOUT.puts [context.stats]
context.perform
end
# Durian
dns_servers = [] of Durian::Resolver::Server
dns_servers << Durian::Resolver::Server.new ipAddress: Socket::IPAddress.new("8.8.8.8", 53_i32), protocol: Durian::Protocol::UDP
dns_servers << Durian::Resolver::Server.new ipAddress: Socket::IPAddress.new("1.1.1.1", 53_i32), protocol: Durian::Protocol::UDP
dns_resolver = Durian::Resolver.new dns_servers
dns_resolver.ip_cache = Durian::Cache::IPAddress.new
# Herbal
tcp_server = TCPServer.new "0.0.0.0", 1234_i32
herbal = Herbal::Server.new tcp_server, dns_resolver
herbal.authentication = Herbal::Authentication::NoAuthentication
herbal.client_timeout = Herbal::TimeOut.new
herbal.remote_timeout = Herbal::TimeOut.new
# Authentication (Optional)
# herbal.authentication = Herbal::Authentication::UserNamePassword
# herbal.on_auth = ->(user_name : String, password : String?) do
# STDOUT.puts [user_name, password]
# Herbal::Verify::Pass
# end
loop do
socket = herbal.accept?
spawn do
next unless client = socket
next unless context = herbal.upgrade client
handle_client context
end
end
STDOUT.puts context.stats # => Herbal::Stats(@version=V5, @authenticationMethods=[NoAuthentication], @command=TCPConnection, @addressType=Domain, @destinationIpAddress=nil, @destinationAddress=#<Herbal::DestinationAddress:0x13f0a9340 @host="api.github.com", @port=443>)
Add this to your application's shard.yml:
dependencies:
herbal:
github: 636f7374/herbal.cr
$ git clone https://github.com/636f7374/herbal.cr.git
$ make test
- Official | Wikipedia - SOCKS
- Official | RFC 1928 - SOCKS Protocol Version 5 - IETF Tools
- Document | How Socks 5 Works
- Document | SOCKS 5 - A Proxy Protocol
- Document | Implement SOCKS5 Protocol
Name | Creator | Maintainer | Contributor |
---|---|---|---|
636f7374 | √ | √ |
- BSD 3-Clause Clear License