Conversation
| if proxies? | ||
| best_comm = Rex::Socket::Comm::Local | ||
| elsif server && localhost |
There was a problem hiding this comment.
Right now, only the local comm supports proxied connections. If a comm is specified, the proxy options are silently ignored. This seems like a problem. Solutions are probably to:
- Warn that proxies will be ignored.
- Raise an exception that the selected comm doesn't support proxies.
- Refactor proxy connection login into a mixin that can be included into any comm. The comm would be used to establish the connection to the first proxy in the chain, then it'd continue on from there. This would be the most difficult option and is thus left out of scope for this change set.
Kind of related is the fact that proxies are ignored for non-TCP socket types. Also seems like a problem, but supporting proxies in comms won't change that. SOCKS4 and HTTP simply don't support UDP and they never will.
| resp = Rex::Proto::Http::Response.new | ||
| resp.update_cmd_parts(ret.split(/\r?\n/)[0]) | ||
| if (match = ret.match(/HTTP\/.+?\s+(\d+)\s?.+?\r?\n?$/)) | ||
| status_code = match[1].to_i | ||
| end |
There was a problem hiding this comment.
This fixed a bug where an exception would be raised if Rex::Socket was used out side the context of Metasploit because Rex::Proto::Http::Response is unavailable. The other proxies just do the bare minimum parsing necessary to ensure the connection was established, so that pattern was copied here as well. Removing this dependency also means the HTTP proxy can be tested in the specs.
f372719 to
c5281fb
Compare
Only the local comm supports proxies. This makes the priority: 1. The explicit comm that was set 2. Local if any proxies where set 3. The comm selected from the switchboard 4. The local comm
It doesn't exist here, so just do some simple parsing like the other proxy protocol handlers do.
c5281fb to
a19f90f
Compare
This adds SOCKS5H support to Rex::Socket, allowing TCP connections established with the local comm to be made through SOCKS5 proxies. The difference between SOCKS5 and SOCKS5H is where hostnames are resolved to DNS. There is a common convention where SOCKS5 proxy clients (including Metasploit) resolve hostnames themselves and issue the IP address to the SOCKS server when connecting. SOCKS5H on the other hand is an unofficial standard whereby the hostname is passed to the SOCKS server, allowing it to be resolved by the proxy instead of Metasploit.
These changes lay the ground work for Metasploit to support both conventions. There will be a PR to rapid7/metasploit-framework shortly that will take advantage of these changes.
This PR also adds a number of unit tests to show how proxies are handled and ensure resolution does and does not happen when appropriate.
Proxy Strings
Proxies are now parsed into URI instances instead of arrays. This means Ruby's builtin
URIclass and it's parsing capabilities can be leveraged instead of using a custom solution. In the future this should also allow additional options to be specified in the URI, so if an HTTP proxy requires authentication, it can be specified in the URI. The//part of the URi is optional to ensure backwards compatibility, e.g.http:localhost:8080will still work but it's normalized tohttp://localhost:8080under the hood so it can be processed as a URI.Test Script
This test script will target an SSH server on TCP port 22 which works well as a test case because SSH will send it's banner, showing that the connection was established. This script allows a proxy to be set so a user can interactively observe how their options affect the socket creation. Use wireshark to check the connect request made to the SOCKS server to see if a hostname or IP address was sent.