Skip to content

Conversation

sebyx07
Copy link
Contributor

@sebyx07 sebyx07 commented May 14, 2025

socks 5 support,

example:

# SOCKS5 proxy details
proxy_host = "98.170.57.241"
proxy_port = 4145

begin
  # Make the request through SOCKS5 proxy
  response = HTTP
             .via_socks5(proxy_host, proxy_port)
             .get("http://ifconfig.me/ip")

  puts "Response status: #{response.status}"
  puts "Response body: #{response.body}"
rescue => e
  puts "Error: #{e.class} - #{e.message}"
  puts e.backtrace
end

This was referenced May 14, 2025
@sebyx07
Copy link
Contributor Author

sebyx07 commented May 16, 2025

hey, do u need any more changes for this to get merged?

@andrepcg
Copy link

cc @tarcieri this would be very helpful

@tarcieri
Copy link
Member

@ixti can you take a look at this one?

@ixti
Copy link
Member

ixti commented Jun 20, 2025

@sebyx07 Thank you for the PR, can you please:

  1. rebase it on top of main
  2. remove Ruby-3.4 related fixes (like those s/inspect/to_json/) - we will deal with them later
  3. Use constants instead of magic numbers (e.g. ADDR_IPV4 = 0x01 instead of using value directly with comment), something like:
    module HTTP
      # SOCKS5 proxy implementation
      class SOCKS5Proxy
        ADDR_IPV4   = 0x01
        ADDR_DOMAIN = 0x03
        ADDR_IPV6   = 0x04
    
        IPV4_RE = /\A\d+\.\d+\.\d+\.\d+\z/
    
        ERR_MESAGES = {
          0x01 => "general SOCKS server failure",
          0x02 => "connection not allowed by ruleset",
          0x03 => "Network unreachable",
          0x04 => "Host unreachable",
          0x05 => "Connection refused",
          0x06 => "TTL expired",
          0x07 => "Command not supported",
          0x08 => "Address type not supported"
        }.freeze
    
        # ...
    
        # Handle the reply code from the SOCKS5 proxy
        # @param [Integer] reply The reply code
        # @raise [HTTP::ConnectionError] if the reply indicates an error
        def handle_reply_code(reply)
          return if reply.zero?
    
          @failed_connect = true
          error_message = ERR_MESAGES.fetch(reply, "Unknown error (code: #{reply})")
          raise ConnectionError, "SOCKS5 proxy connection failed: #{error_message}"
        end
    
        # Skip the bound address and port in the response
        # @param [Integer] atyp The address type
        # @return [void]
        def skip_bound_address(atyp)
          case atyp
          when ADDR_IPV4
            @socket.readpartial(6) # 4 bytes for IPv4 + 2 bytes for port
          when ADDR_DOMAIN
            domain_len = @socket.readpartial(1).unpack1("C")
            @socket.readpartial(domain_len + 2) # domain length + 2 bytes for port
          when ADDR_IPV6
            @socket.readpartial(18) # 16 bytes for IPv6 + 2 bytes for port
          end
        end
      end
    end

Also, I've noticed that skip_bound_address handles IPV6, but format_address does not, is that intentional?

spec/examples.txt
tmp
Gemfile.lock
.idea/
Copy link
Contributor

@tycooon tycooon Jun 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to put stuff like this in your global gitignore file, so that you don't have to add it in every project.

@sebyx07
Copy link
Contributor Author

sebyx07 commented Jun 25, 2025

i'm busy with my work right now, you can fork my code and do the required updates, i have my own fork self hosted http gem anyway, i don't like to rely on others for mergex/fixes etc

@sebyx07
Copy link
Contributor Author

sebyx07 commented Jun 25, 2025

i just shared it with you in case you want to add it to the public gem

@ixti
Copy link
Member

ixti commented Jun 26, 2025

@sebyx07 thank you!

@ixti ixti added this to the v6.0.0 milestone Jun 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants