Skip to content

Commit fbff1bd

Browse files
committed
Add Socks v4 support to daemon and wallet
1 parent 8d6aff9 commit fbff1bd

File tree

17 files changed

+1532
-78
lines changed

17 files changed

+1532
-78
lines changed

docs/proxies.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# Proxy usage in the Monero ecosystem
2+
The CLI/RPC wallets and daemon both support proxies and use the same parameters
3+
to configure them. Currently socks 4, 4a, and 5 are supported and can be
4+
selected with command-line options.
5+
6+
## Wallet
7+
The CLI and RPC wallets support proxies via the `--proxy` option. The format
8+
for usage is `[socks5://[user:pass]]host:port`. The square brackets indicate
9+
an optional portion. This option can only be specified once. Examples:
10+
11+
```
12+
--proxy 192.168.0.10:1050
13+
--proxy socks5://192.168.0.10:1050
14+
--proxy socks5://username:password@192.168.0.10:1050
15+
--proxy [::1]:1050
16+
--proxy socks5://[::1]:1050
17+
--proxy socks5://username:password@[::1]:1050
18+
```
19+
20+
The first connects to `192.168.0.10` on port `1050` using socks 4a. The second
21+
connects to the same location using socks 5. The third uses socks 5 at the same
22+
location and sends user authentication if prompted by the proxy server. The
23+
last three are identical to the first 3, except an IPv6 address is used
24+
instead. While IPv6 connections are invalid for Socks 4 and 4a, the proxy
25+
server itself can be connected using IPv6.
26+
27+
The username and password fields both support "percent-encoding" for special
28+
character support. As an example, `%40` gets converted to `@`, such that
29+
`username:p%40ssword` gets converted to `username:p@ssword`. This allows that
30+
specific character to be used; specifying the character directly will
31+
incorrectly change the specification of the hostname.
32+
33+
> NOTE: The username+password will show up in the process list and can be read
34+
> by other programs. It is recommended that `--config-file` be used to store
35+
> username+password options. The format for a config file is `option=value`,
36+
> so in this example the file would contain:
37+
> `proxy=socks5://username:password@192.168.0.10:1080`.
38+
39+
The CLI and RPC wallets currently reject hosts that do **NOT** end in`.onion`
40+
or `.i2p` **unless** `--daemon-ssl-ca-certificates`,
41+
`--daemon-ssl-allow-any-cert`, or `--daemon-ssl-allowed-fingerprints` is used.
42+
If an onion or i2p address is used, the hostname contains the certificate
43+
verification, providing decent security against man-in-the-middle (MitM)
44+
attacks. The two `--daemon-ssl-*` options support specifying exact
45+
certificates, also preventing MitM attacks.
46+
47+
> Perhaps the wallets should be relaxed to allow system-CA checks, but for now
48+
> certificates must be strictly provided.
49+
50+
## Daemon
51+
The daemon has two options for proxies `--proxy` and `--tx-proxy` which can be
52+
used in isolation or together. The `--proxy` option controls how
53+
IPv4/IPv6/hostname connections are performed, whereas `--tx-proxy` controls
54+
how local transactions are relayed. Both options support Socks 4, 4a, and 5.
55+
56+
### `--proxy`
57+
This option should be used when outbound connections to IPv4/IPv6 addresses and
58+
hostnames (other than `.onion` `.i2p`) need to be proxied. Common examples
59+
include using Tor exit nodes or a VPN to conceal your local IP. This option
60+
will **not** use Tor or I2P hidden services for P2P connections; this is
61+
primarily used for proxying standard IPv4 or IPv6 connections to some remote
62+
host. Hidden services are not used because this is designed to be more general
63+
purpose (i.e. a standard socks VPN can be used).
64+
65+
> An additional option for hidden services (separate from `--tx-proxy`) could
66+
> arguably be added, which could optionally turn off IPv4/IPv6 connections for
67+
> P2P.
68+
69+
The format for `--proxy` usage: `[socks5://[user:pass]]@127.0.0.1`. The square
70+
bracket indicate optional portion. See [wallet](#wallet) section above for
71+
examples and other information on the format. The option can only be specified
72+
once. The restrictions for MitM attacks apply only to the wallet usage, and not
73+
to the daemon.
74+
75+
> When using `--proxy`, inbound connections will be impossible unless the
76+
> proxy server is somehow setup to forward connections. This setup is a
77+
> difficult because each outgoing socks connections can have a unique binding
78+
> port. Such a setup is currently out-of-scope for this document.
79+
80+
### `--tx-proxy`
81+
This option should be used to specify a proxy that can resolve hidden service
82+
hostnames, so that local transactions can be forwarded over a privacy
83+
preserving network. Currently only Tor or I2P hidden services are supported.
84+
This option be specified multiple times, but only once per network (see below).
85+
86+
The format for `--tx-proxy` is
87+
`network,[socks5://[user:pass@]]ip:port[,max_connections][,disable_noise]`.
88+
Examples:
89+
90+
```
91+
--tx-proxy tor,127.0.0.1:1050
92+
--tx-proxy tor,127.0.0.1:1050,100
93+
--tx-proxy tor,127.0.0.1:1050,disable_noise
94+
--tx-proxy tor,127.0.0.1:1050,100,disable_noise
95+
--tx-proxy tor,socks5://127.0.0.1:1050
96+
--tx-proxy tor,socks5://127.0.0.1:1050,100
97+
--tx-proxy tor,socks5://127.0.0.1:1050,disable_noise
98+
--tx-proxy tor,socks5://127.0.0.1:1050,100,disable_noise
99+
--tx-proxy tor,socks5://username:password@127.0.0.1:1050
100+
--tx-proxy tor,socks5://username:password@127.0.0.1:1050,100
101+
--tx-proxy tor,socks5://username:password@127.0.0.1:1050,disable_noise
102+
--tx-proxy tor,socks5://username:password@127.0.0.1:1050,100,disable_noise
103+
--tx-proxy tor,[::1]:1050
104+
--tx-proxy tor,[::1]:1050,100
105+
--tx-proxy tor,[::1]:1050,disable_noise
106+
--tx-proxy tor,[::1]:1050,100,disable_noise
107+
--tx-proxy tor,socks5://[::1]:1050
108+
--tx-proxy tor,socks5://[::1]:1050,100
109+
--tx-proxy tor,socks5://[::1]:1050,disable_noise
110+
--tx-proxy tor,socks5://[::1]:1050,100,disable_noise
111+
--tx-proxy tor,socks5://username:password@[::1]:1050
112+
--tx-proxy tor,socks5://username:password@[::1]:1050,100
113+
--tx-proxy tor,socks5://username:password@[::1]:1050,disable_noise
114+
--tx-proxy tor,socks5://username:password@[::1]:1050,100,disable_noise
115+
--tx-proxy i2p,127.0.0.1:1050
116+
--tx-proxy i2p,127.0.0.1:1050,100
117+
--tx-proxy i2p,127.0.0.1:1050,disable_noise
118+
--tx-proxy i2p,127.0.0.1:1050,100,disable_noise
119+
--tx-proxy i2p,socks5://127.0.0.1:1050
120+
--tx-proxy i2p,socks5://127.0.0.1:1050,100
121+
--tx-proxy i2p,socks5://127.0.0.1:1050,disable_noise
122+
--tx-proxy i2p,socks5://127.0.0.1:1050,100,disable_noise
123+
--tx-proxy i2p,socks5://username:password@127.0.0.1:1050
124+
--tx-proxy i2p,socks5://username:password@127.0.0.1:1050,100
125+
--tx-proxy i2p,socks5://username:password@127.0.0.1:1050,disable_noise
126+
--tx-proxy i2p,socks5://username:password@127.0.0.1:1050,100,disable_noise
127+
--tx-proxy i2p,[::1]:1050
128+
--tx-proxy i2p,[::1]:1050,100
129+
--tx-proxy i2p,[::1]:1050,disable_noise
130+
--tx-proxy i2p,[::1]:1050,100,disable_noise
131+
--tx-proxy i2p,socks5://[::1]:1050
132+
--tx-proxy i2p,socks5://[::1]:1050,100
133+
--tx-proxy i2p,socks5://[::1]:1050,disable_noise
134+
--tx-proxy i2p,socks5://[::1]:1050,100,disable_noise
135+
--tx-proxy i2p,socks5://username:password@[::1]:1050
136+
--tx-proxy i2p,socks5://username:password@[::1]:1050,100
137+
--tx-proxy i2p,socks5://username:password@[::1]:1050,disable_noise
138+
--tx-proxy i2p,socks5://username:password@[::1]:1050,100,disable_noise
139+
```
140+
141+
The above examples are fairly exhaustive of all the possible option scenarios
142+
that will be incurred by the typical user.
143+
144+
#### The `network` portion of the option
145+
The first section (before the first `,`) indicates the network - only `tor` or
146+
`i2p` are valid here.
147+
148+
This portion of the option tells `--add-node`, `--add-priority-node`, and
149+
`--add-exclusive-node` options to use the specified proxy for those nodes. In
150+
other words, command-line specified hidden services are forwarded to their
151+
corresponding `--tx-proxy` server. Hidden services do **NOT** have to be
152+
specified on the command-line, there are built-in seed nodes for each network.
153+
154+
#### The `ip:port` portion of the option
155+
The second portion of the option (after the first `,` and _optionally_ ending
156+
in the next `,`) indicates the location of the socks server. The location
157+
**must** include an IPv4/IPv6 AND port. The location can optionally include the
158+
socks version - `socks4`, `socks4a`, and `socks5` are all valid here. If
159+
the socks version is not specified, `socks4a` is assumed.
160+
161+
An optional username and password can also be included. These fields support
162+
percent-encoding, see [wallet](#wallet) section for more information.
163+
164+
#### The last portion of the option
165+
After the ip:port section two options can be specified: the number of max
166+
connections and `disable_noise`. They can be specified in either order, but
167+
must be after the ip:port section.
168+
169+
The max connections does exactly as advertised, it limits the number of
170+
outgoing connections to the proxy. The `disable_noise` feature lowers the
171+
bandwidth requirements, and decreases the tx-relay time. When **NOT**
172+
specified, dummy P2P packets are sent periodically to connections (via the
173+
proxy) to conceal when a transaction is forwarded over the connection. When
174+
the option is specified, P2P links only send data for peerlist information and
175+
local outgoing transactions.
176+
177+
### `--anonymous-inbound`
178+
Currently the daemon cannot configure incoming hidden services connections.
179+
Instead, the user must manually configure Tor or I2P to accept inbound
180+
connections. Then, `--anonymous-inbound` must be used to tell the daemon where
181+
to listen for incoming connections, and the incoming hidden service address.
182+
The option can be specified once for each network type. The format for usage
183+
is: `hidden-service-address,[bind-ip:]port[,max_connections]`. Examples:
184+
185+
```
186+
--anonymous-inbound rveahdfho7wo4b2m.onion:18083,18083
187+
--anonymous-inbound rveahdfho7wo4b2m.onion:18083,18083,100
188+
--anonymous-inbound rveahdfho7wo4b2m.onion:18083,127.0.0.1:18083
189+
--anonymous-inbound rveahdfho7wo4b2m.onion:18083,127.0.0.1:18083,100
190+
--anonymous-inbound udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p,18083
191+
--anonymous-inbound udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p,18083,100
192+
--anonymous-inbound udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p,127.0.0.1:18083
193+
--anonymous-inbound udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p,127.0.0.1:18083,100
194+
```
195+
196+
Everything before the first `,` is the hidden service hostname. This must be
197+
a valid Tor or I2P address. This tells the daemon the **inbound** hidden
198+
service as configured for the local Tor or I2P daemons.
199+
200+
Everything between `,`s specify the bind ip and bind port. The IP address is
201+
optional, and defaults to `127.0.0.1`. The Tor and I2P daemons must be
202+
configured to forward incoming hidden service connections to this IP/Port pair.
203+
204+
Everything after the second `,` is used to specify the number of max inbound
205+
connections. The field is optional.

src/daemon/command_line_args.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ namespace daemon_args
9494

9595
const command_line::arg_descriptor<std::string> arg_proxy = {
9696
"proxy",
97-
"Network communication through proxy: <socks-ip:port> i.e. \"127.0.0.1:9050\"",
97+
"Network communication through proxy: [socks5://[user:pass@]]<socks-ip:port> i.e. \"127.0.0.1:9050\"",
9898
"",
9999
};
100100
const command_line::arg_descriptor<bool> arg_proxy_allow_dns_leaks = {

src/net/error.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ namespace
5454
return "Failed to retrieve desired DNS record";
5555
case net::error::expected_tld:
5656
return "Expected top-level domain";
57+
case net::error::invalid_encoding:
58+
return "Invalid encoding";
5759
case net::error::invalid_host:
5860
return "Host value is not valid";
5961
case net::error::invalid_i2p_address:
@@ -62,8 +64,12 @@ namespace
6264
return "CIDR netmask outside of 0-32 range";
6365
case net::error::invalid_port:
6466
return "Invalid port value (expected 0-65535)";
67+
case net::error::invalid_scheme:
68+
return "Invalid/unsupported scheme was provided";
6569
case net::error::invalid_tor_address:
6670
return "Invalid Tor address";
71+
case net::error::unexpected_userinfo:
72+
return "User or pass was provided unexpectedly";
6773
case net::error::unsupported_address:
6874
return "Network address not supported";
6975
default:

src/net/error.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ namespace net
4141
bogus_dnssec = 1, //!< Invalid response signature from DNSSEC enabled domain
4242
dns_query_failure, //!< Failed to retrieve desired DNS record
4343
expected_tld, //!< Expected a tld
44+
invalid_encoding, //!< Invalid percent encoding
4445
invalid_host, //!< Hostname is not valid
4546
invalid_i2p_address,
4647
invalid_mask, //!< Outside of 0-32 range
4748
invalid_port, //!< Outside of 0-65535 range
49+
invalid_scheme, //!< Provided URI scheme was unspported
4850
invalid_tor_address,//!< Invalid base32 or length
51+
unexpected_userinfo,//!< User or pass was provided unexpectedly
4952
unsupported_address,//!< Type not supported by `get_network_address`
5053

5154
};

src/net/fwd.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,19 @@
3434
namespace net
3535
{
3636
enum class error : int;
37+
struct scheme_and_authority;
3738
class tor_address;
39+
struct uri_components;
40+
struct user_and_pass;
41+
struct userinfo_and_hostport;
3842
class i2p_address;
3943

4044
namespace socks
4145
{
4246
class client;
4347
template<typename> class connect_handler;
48+
struct connector;
49+
struct endpoint;
4450
enum class error : int;
4551
enum class version : std::uint8_t;
4652
}

src/net/http.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,17 @@ bool client::set_proxy(const std::string &address)
4545
}
4646
else
4747
{
48-
const auto endpoint = get_tcp_endpoint(address);
48+
auto endpoint = socks::endpoint::get(address);
4949
if (!endpoint)
5050
{
51-
auto always_fail = net::socks::connector{boost::asio::ip::tcp::endpoint()};
51+
auto always_fail = net::socks::connector{};
5252
set_connector(always_fail);
5353
}
5454
else
5555
{
56-
set_connector(net::socks::connector{*endpoint});
56+
set_connector(
57+
net::socks::connector{std::make_shared<socks::endpoint>(std::move(*endpoint))}
58+
);
5759
}
5860
}
5961

0 commit comments

Comments
 (0)