Open woodser opened 3 weeks ago
The HiddenServicePoWDefensesEnabled
flag can be applied by modifying haveno.properties within the application directory:
torrcOptions=HiddenServicePoWDefensesEnabled 1
However, this leads to a startup error:
Jul-10 08:26:44.446 [StartTor] ERROR h.network.p2p.network.TorNetworkNode: Starting tor node failed org.berndpruenster.netlayer.tor.TorCtlException: Could not setup Tor
at org.berndpruenster.netlayer.tor.NativeTor.<init>(NativeTor.kt:106)
at org.berndpruenster.netlayer.tor.NativeTor.<init>(NativeTor.kt:55)
at org.berndpruenster.netlayer.tor.NativeTor.<init>(NativeTor.kt)
at haveno.network.p2p.network.NewTor.getTor(NewTor.java:110)
at haveno.network.p2p.network.TorNetworkNode.lambda$createTorAndHiddenService$10(TorNetworkNode.java:172)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.io.IOException: java.io.IOException: Tor exited with value 1
at org.berndpruenster.netlayer.tor.TorContext.installAndStartTorOp(TorContext.kt:392)
at org.berndpruenster.netlayer.tor.NativeTor.<init>(NativeTor.kt:66)
... 8 common frames omitted
Caused by: java.io.IOException: Tor exited with value 1
at org.berndpruenster.netlayer.tor.TorContext.installAndStartTorOp(TorContext.kt:354)
... 9 common frames omitted
So now this issue needs to resolve that error.
There is a bounty on this issue, the amount is in the title. The reward will be awarded to the first person or group of people who resolves this issue.
If you are starting to work on this bounty, please write a comment, so that we can assign the issue to you. We expect contributors to provide a PR in a reasonable time frame or, in case of an extensive work, updates on their progresses. We will unassign the issue if we feel the assignee is not responsive or has abandoned the task.
Read the full conditions and details of our bounty system.
HiddenService options are per onion service you can't just put them in torrc. See my example in the message tor-relays@lists.tpo
I think it was more likely an attack against which POW is ineffective (OOM-Killer) A case study on DDoS attacks against Tor relays
How about if I make a PR to activate IntroDoSDefense in addition to PoWDefenses
HiddenServiceEnableIntroDoSDefense 1
#HiddenServiceEnableIntroDoSBurstPerSec 200 # (Default: 200)
#HiddenServiceEnableIntroDoSRatePerSec 25 # (Default: 25)
Then we can temporarily activate the metrics port in torrc on the seed nodes
MetricsPort 127.0.0.1:9035
MetricsPortPolicy accept 127.0.0.1
and see statistics like: tor_relay_intro1_total{action="rate_limited"} 5857
I think #1012 by @preland is correct, I have in
$ curl http://127.0.0.1:9235/metrics
...
# TYPE tor_hs_pow_suggested_effort gauge
tor_hs_pow_suggested_effort{onion="current.rreto-mainnet.seednode"}
...
Sounds ok to me. I don't know much about Tor config so will defer.
https://github.com/haveno-dex/haveno/pull/1129 I will instruct the reto seednode operators to enable the metrics port so that we can retrieve tor metrics. For testing purposes, I have a seed node running in the reto network.
Since the options are per onion service and the Haveno hidden service is created dynamically via the control port, parameters can only be changed via rebuild. We currently have the default settings. If necessary, we have to adjust PoW and IntroDoS parameters in the network. (Means, in reto github)
HiddenServicePoWQueueRate
& HiddenServicePoWQueueBurst
HiddenServiceEnableIntroDoSRatePerSec
& HiddenServiceEnableIntroDoSBurstPerSec
And maybe even:
HiddenServiceMaxStreams
& HiddenServiceMaxStreamsCloseCircuit
PR #1012 and #1129 are modifications to the torrc file of the "relay" app, which is a service to relay client notifications to users' mobile devices (via google or whatever). The seednode app is unrelated to "relay".
Seednode is quite similar to regular haveno clients such as desktop and daemon. It creates its hidden service programmatically via the tor control port as @boldsuck stated above. The code flow goes through netlayer and jtorctl (separate sub-projects), sending ADD_ONION
to the control port. Perhaps at that time, the hiddenservice options can be configured programmatically via SETCONF
? What's not clear is how the configuration parameters can be associated with the just-created hiddenservice.
Also, haveno is still using the jtorctl binary from bisq.
I will try to find solutions, but I'm not a dev. I'll add 0.3 XMR from myself to the Bounty. I'm afraid it's not easy to enable PoW because the bisq dev's only have it in Bisq2.
Hints:
A 'real' hidden service generated by c-tor has a ed25519 secret and ed25519 public key. If a Haveno seednode can read them, then you should be able to create the hidden service in the system tor torrc. (like monerod) And then it is very easy to configure all hs parameters.
Attempting to configure the same HS in torrc and netlayer produces an error "hidden service collision" when netlayer starts.
Alternatively, this patch allows netlayer to be bypassed so that a HS can be used and configured in torrc. It may be experimental & ugly, but it should help investigating if Tor DoS protection does solve the issue.
We're targeting to release within a few days, if it's possible to do anything before then.
Bounty bumped to 1 XMR.
Attempting to configure the same HS in torrc and netlayer produces an error "hidden service collision" when netlayer starts.
Yes, I have tried something similar. Then my client or seednode had 2 hidden.service .onion addresses.
Alternatively, this patch allows netlayer to be bypassed so that a HS can be used and configured in torrc. It may be experimental & ugly, but it should help investigating if Tor DoS protection does solve the issue.
I don't think there's any other way. In Tor control-spec ADD_ONION are available at 'Flag' as hidden service options only: MaxStreamsCloseCircuit & NumStreams = HiddenServiceMaxStreamsCloseCircuit
& HiddenServiceMaxStreams
With your patch all onion service options could be configured. IntroDoS, PoW & MaxStreams :-)
Great, thanks for trying it! Would be good to know if the patch & those settings solves the perceived problem too.
So to clarify, in order to run with proof of work defense enabled:
Questions:
Ideally it's all preconfigured out of the box, and even the seed node operators don't need to take any extra steps. Not sure I'm following the overall steps here.
Damn, the build always failed. Hard drive has errors. Now I know why the machine always breaks the Monero Stressnet Node database. ;-)
So to clarify, in order to run with proof of work defense enabled:
1. Apply fa2a5qj3's [patch](https://gist.github.com/fa2a5qj3/57219580e7ce746aa45ac6edf4682238#file-externaltordirectbind3-patch).
The build is running fine on a second server. Patch applyed to haveno-reto
2. Configure the options for torcc normally?
I'll try this right away with system torrc & haveno_seednode home folder torrc.
Questions:
* Any reason the patch shouldn't be opened as a PR and merged into the project?
AFAIK the seed nodes get new .onion addresses because ed25519 keys are generated. I think we should test this first and coordinate it among the seed node operators. This doesn't have to be rushed into version 1.0.9
* Must the seednode be started with a hidden service address? It already knows its own address after starting up.
Yes, because no control port is used anymore.
As with monerod: Configure tor hidden service, start tor, cat /var/lib/tor/hidden-service/hostname
and start seednode with the address.
* Can the torcc options be preconfigured so one doesn't need to add them manually?
You could write the entire torrc in ~/.local/share/haveno_seednode/xmr_mainnet/tor/
.
Or in system tor /etc/tor/torrc
I add the Haveno hidden service with the %include /etc/tor/torrc.seednode
line.
* Does Bisq2's approach offer any advantages, or can/should we migrate to what they did?
I haven't looked into it yet. You can create multiple accounts and have multiple hidden services in the Bisq2 desktop app.
Sounds like a significant change that would require quite a bit of testing and couldn't be released any time soon.
I'm wondering why it's so difficult, that the option doesn't work from startup flags.
We're looking for something that is more straight forward for the short term.
Does Bisq2's approach offer any advantages, or can/should we migrate to what they did?
Bisq2 took the approach of writing their own PoW at the application protocol level, and have not enabled Tor's lower level PoW settings. They also configure Tor HS via the control port, presumably DoS currently not a supported configuration option there.
Creating a new PoW at the application protocol level would be a major change. Bisq2 did it in a complete rewrite.
I'm wondering why it's so difficult, that the option doesn't work from startup flags.
That would be a question / request for the Tor project:
Either one of the above would solve the problem.
EDIT: I was stupid. Port was below 1024. Port 9992 works ;-)
Damn I have: java.lang.RuntimeException: Permission denied
haveno-user is in tor group
user@crypto-01:~$ groups
user debian-tor
root@crypto-01:~# systemctl status haveno-seednode
● haveno-seednode.service - Haveno seednode
Loaded: loaded (/etc/systemd/system/haveno-seednode.service; enabled; preset: enabled)
Active: active (running) since Tue 2024-07-16 18:06:14 CEST; 4s ago
Main PID: 335613 (java)
Tasks: 31 (limit: 38362)
Memory: 164.9M
CPU: 9.621s
CGroup: /system.slice/haveno-seednode.service
└─335613 java -classpath /home/user/haveno-reto/lib/seednode.jar:/home/user/haveno-reto/lib/core.jar:/home/user/haveno-reto/lib/p2p.jar:/home/user/haveno-reto/lib/common.jar:/home/user/haveno-reto/lib/proto.jar:/home/user/>
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.net.ServerSocket.bind(ServerSocket.java:391)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.net.ServerSocket.<init>(ServerSocket.java:278)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.net.ServerSocket.<init>(ServerSocket.java:171)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at haveno.network.p2p.network.TorNetworkNode.lambda$createTorAndHiddenService$6(TorNetworkNode.java:178)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.lang.Thread.run(Thread.java:1583)
Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: Jul-16 18:06:17.729 [SeedNodeMain] ERROR haveno.core.app.misc.AppSetupWithP2P: java.lang.RuntimeException: Permission denied
With the patch, the seednode only runs with system tor. Create a hidden service in /etc/tor/torrc
or /etc/tor/instances/*/torrc
usermod -aG debian-tor haveno-seednode-user
In the haveno-seednode.service script, only the line hiddenServiceAddress=
needs to be added.
And we can now also use full-vanguards. ;-)
Creating a new PoW at the application protocol level would be a major change. Bisq2 did it in a complete rewrite.
I wonder why they re-wrote this. Tor's PoW is the Equihash PoW algorithm using HashX as underlying hash function. This is derived from the RandomX hash function used in Monero's Hashcash PoW algorithm. Developed by @tevador https://github.com/tevador/equix/blob/master/devlog.md
I'm wondering why it's so difficult, that the option doesn't work from startup flags.
That would be a question / request for the Tor project:
* can the control port allow HS to be fully configured with DoS protection?
I'll ask Roger & Matt that at the next Tor relay meetup. Actually, I can say it now with 99% certainty. It is not in the Tor control spec. Nothing (big) will change for C-Tor, it is frozen. All Tor devs are working hard on Arti - A Tor implementation in Rust.
* can torrc allow an overall configuration to enable DoS protection of all HS?
Definitely not. There are these per onion service options and overall DoS configuration for which by default Tor directory authorities will define reasonable values for the network. Consensus Health -> consensus
man tor
DENIAL OF SERVICE MITIGATION OPTIONS
HIDDEN SERVICE OPTIONS
EDIT: I was stupid. Port was below 1024. Port 9992 works ;-)
Damn I have: java.lang.RuntimeException: Permission denied
haveno-user is in tor group
user@crypto-01:~$ groups user debian-tor
root@crypto-01:~# systemctl status haveno-seednode ● haveno-seednode.service - Haveno seednode Loaded: loaded (/etc/systemd/system/haveno-seednode.service; enabled; preset: enabled) Active: active (running) since Tue 2024-07-16 18:06:14 CEST; 4s ago Main PID: 335613 (java) Tasks: 31 (limit: 38362) Memory: 164.9M CPU: 9.621s CGroup: /system.slice/haveno-seednode.service └─335613 java -classpath /home/user/haveno-reto/lib/seednode.jar:/home/user/haveno-reto/lib/core.jar:/home/user/haveno-reto/lib/p2p.jar:/home/user/haveno-reto/lib/common.jar:/home/user/haveno-reto/lib/proto.jar:/home/user/> Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:636) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.net.ServerSocket.bind(ServerSocket.java:391) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.net.ServerSocket.<init>(ServerSocket.java:278) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.net.ServerSocket.<init>(ServerSocket.java:171) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at haveno.network.p2p.network.TorNetworkNode.lambda$createTorAndHiddenService$6(TorNetworkNode.java:178) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: at java.base/java.lang.Thread.run(Thread.java:1583) Jul 16 18:06:17 crypto-01 Haveno-Seednode[335613]: Jul-16 18:06:17.729 [SeedNodeMain] ERROR haveno.core.app.misc.AppSetupWithP2P: java.lang.RuntimeException: Permission denied
Odd; have you tried to run the binary directly with that user? My guess is that the process isn't getting spawned with the correct user privileges. If running the seednode as root results in the same issue, that might be the case.
I am currently unable to work on this issue until late on Saturday, so if woodser needs this issue addressed before then, I won’t be available outside of infrequent passive commentary.
It was only because port was less than 1024.
This is because of the CapabilityBoundingSet= in /usr/lib/systemd/system/tor@default.service
or in /usr/lib/systemd/system/tor@.service
if you create multiple tor instances.
To avoid making things more complicated¹, I use ports over 1023. ¹(systemd-overrides and changing AppArmor or SELinux settings)
I am currently preparing a Haveno-reto fork with patch from @fa2a5qj3 & a finished torrc and instructions for the seed node operators.
EDIT: Haveno now uses Tor SocksPort. haveno-user does not have to be in the tor group.
I am currently preparing a Haveno-reto fork with patch from @fa2a5qj3 & a finished torrc and instructions for the seed node operators.
This runs on the mainnet when the clients upgrade to 1.0.9. https://github.com/boldsuck/haveno-reto Patch und config synced with Haveno-Dex https://github.com/boldsuck/haveno
2 seed nodes are running with v.1.0.9 & the patch in the mainnet since yesterday. The 3rd is ready to take action. Clients can connect, here are the logs: http://boldsuck.mynetcologne.de/doc/haveno.log_s0 http://boldsuck.mynetcologne.de/doc/haveno.log_s3
These are probably warning messages because peers are no longer reachable.
WARN h.n.p.n.TorNetworkNode: SOCKS error code received 06 expected 00
Some Metrics PoW only works when we are under DDoS.
I added a small Tor install script for Ubuntu/Debian, required torrc and some documentation. It's not finished yet. https://github.com/boldsuck/haveno
I've been spot-testing those new nodes for the past few days with a standard 'reto' client.
Sometimes get an immediate response, othertimes unable to connect and sometimes timeout (no response, 3 minutes).
They do seem more responsive than the other reto nodes, most of which I get no connection ever.
End result, if reto does not start promptly I just resort to shutting down & restarting.
The seednodes running stable with a default 24h restart and I have on both now:
HiddenServicePoWQueueRate 200 # (Default: 250)
HiddenServicePoWQueueBurst 1000 # (Default: 2500)
z47tltuwytd5icqq4hni2ammvlugp6pcwqboeu7ngawruualxjjuu3ad.onion
HiddenServiceMaxStreams 25
xephvvzd3orepnny7lbia4nkwie5t7wjivlvvz5lhbsck7ubavystead.onion
HiddenServiceMaxStreams 25
HiddenServiceMaxStreamsCloseCircuit 1
HiddenServiceMaxStreamsCloseCircuit: If set to 1, then exceeding HiddenServiceMaxStreams will cause the offending rendezvous circuit to be torn down, as opposed to stream creation requests that exceed the limit being silently ignored. I don't know yet which makes more sense.
Sometimes I get 1000s of errors from some clients. But 50-80 peers remain connected.
Haveno-Seednode[108276]: Jul-24 00:07:24.664 [InputHandler-40a69fd7-ace...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.664 [InputHandler-5ed44a72-906...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.665 [InputHandler-8715ec89-36b...] ERROR haveno.network.p2p.network.Connection: Protocol message end-group tag did not match expected tag.
Haveno-Seednode[108276]: Jul-24 00:07:24.665 [InputHandler-40a69fd7-ace...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.665 [InputHandler-8715ec89-36b...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.666 [InputHandler-8715ec89-36b...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.666 [InputHandler-8715ec89-36b...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.734 [InputHandler-3e51d88f-9a0...] ERROR haveno.network.p2p.network.Connection: Protocol message end-group tag did not match expected tag.
Haveno-Seednode[108276]: Jul-24 00:07:24.735 [InputHandler-eccaa8cc-af4...] ERROR haveno.network.p2p.network.Connection: Protocol message end-group tag did not match expected tag.
Haveno-Seednode[108276]: Jul-24 00:07:24.735 [InputHandler-3e51d88f-9a0...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.735 [InputHandler-eccaa8cc-af4...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.735 [InputHandler-3e51d88f-9a0...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.735 [InputHandler-eccaa8cc-af4...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.735 [InputHandler-3e51d88f-9a0...] ERROR haveno.network.p2p.network.Connection: Protocol message end-group tag did not match expected tag.
Haveno-Seednode[108276]: Jul-24 00:07:24.799 [InputHandler-17dedb47-94d...] ERROR haveno.network.p2p.network.Connection: Protocol message end-group tag did not match expected tag.
Haveno-Seednode[108276]: Jul-24 00:07:24.800 [InputHandler-17dedb47-94d...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:24.800 [InputHandler-17dedb47-94d...] ERROR haveno.network.p2p.network.Connection: Protocol message tag had invalid wire type.
Haveno-Seednode[108276]: Jul-24 00:07:29.331 [SeedNodeMain] INFO haveno.network.p2p.peers.PeerManager: We have 59 connections open. Our limit is 500
Unfortunately the patch also affects the clients and arbs informed us @preland.
I'll work on getting that fixed once I get my preliminary work on the universal mac binary for monero-cpp (should have a preliminary PR up either later tonight or sometime tomorrow)
The proof of work DoS protection flag (
HiddenServicePoWDefensesEnabled 1
) was added in https://github.com/haveno-dex/haveno/pull/1012 by @preland.However, the flag is not applied to the seed nodes or app directory's tor directory (i.e. xmr_mainnet/tor/torcc).
This issue requests applying the flag successfully to enable proof of work DoS protection for Tor services.