Herbal.cr - SOCKS5 Client and Server

Description

Features

Tips

Usage

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
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>)

Used as Shard

Add this to your application's shard.yml:

dependencies:
  herbal:
    github: 636f7374/herbal.cr

Installation

$ git clone https://github.com/636f7374/herbal.cr.git

Development

$ make test

References

Credit

Contributors

|Name|Creator|Maintainer|Contributor| |:---:|:---:|:---:|:---:| |**636f7374**|√|√||

License