Skip to content

Conversation

@eval-exec
Copy link
Collaborator

@eval-exec eval-exec commented Dec 2, 2024

What problem does this PR solve?

This PR want to add socks5 proxy and onion support for ckb.

Add network.proxy and network.onion config:

# [network.proxy]
### The proxy_url is user-specified SOCKS5 address, like: socks5://127.0.0.1:7891
# proxy_url = "socks5://127.0.0.1:9050"

### Toggle random authentication for the proxy server.
### Default setting: true
###
### When enabled (true), CKB will generate a random username and password for each connection
### to the proxy server.
### For a Tor Server, this increases privacy by ensuring the proxy cannot correlate
### multiple connections.
### Refer to the 'IsolateSOCKSAuth' section in the following documentation:
### https://manpages.debian.org/testing/tor/torrc.5.en.html
###
### Important Note:
### If you are using a non-Tor SOCKS5 proxy that supports, but does not require authentication,
### enabling this may lead to connection rejections. In such cases, set proxy_random_auth to false.
# proxy_random_auth = true

# [network.onion]
### If CKB needs to run behind the Onion network,
### the user should start a Tor server and set proxy_url to the Tor server's address.
### then MUST set [network.proxy.proxy_url] to tor server's address.
### The default Tor SOCKS5 proxy URL is socks5://127.0.0.1:9050.
### For more information on configuring Tor, visit: https://linux.die.net/man/1/tor

### Enable or disable listening on the Onion network.
### When set to true, CKB will accept incoming connections over Tor.
### You can get the onion listening address in log, or by local_node_info RPC
# listen_on_onion = true

### The onion service will proxy incoming traffic to `p2p_listen_address`.
### If the CKB's peer-to-peer listen address is not set to the default 127.0.0.1
### with the port specified in `[network].listen_addresses` for IPv4, you should configure this field.
# p2p_listen_address = "127.0.0.1:8115"

### The address and port of the Tor SOCKS5 proxy server that CKB will use to establish
### outbound connections to other Onion services. If not set, it will use network.proxy.proxy_url
# onion_server = "127.0.0.1:9050"

### The address and port of the Tor ControlPort, which allows CKB to communicate with
### the Tor process for tasks like creating Onion services.
### Default: "127.0.0.1:9051"
# tor_controller = "127.0.0.1:9051"

### The password for authenticating with the Tor ControlPort.
### This should match the 'HashedControlPassword' set in your Tor configuration.
### Leave empty if no authentication is required.
# tor_password = ""

Start a tor server: tor --SocksPort 9050 --ControlPort 9051, finaly, start the ckb node, if network.onion.listen_on_onion is true, it will auto connect to the tor server, and use tor control port to create onion service.

Related changes

  • Add ProxyConfig and OnionConfig to network config
  • Support socks5 authentication like: socks5://<username>:<password>@server_host:port
  • Support connect to onion ckb node, and listen on the onion hidden network
  • [WIP] Integration test for ckb-onion
    • node1(onion) can succesfully connect node2(node2) in the onion network
    • noode1(onion) can succesfully connect to node2(non-onion)
    • node1(onion) connect node0(onion), node2(onion) connect to node0, expect node1 and node2 can reach each other
    • node1(non-onion) can use [network.proxy] via a normal socks5 proxy
  • ckb-onion related configuration's documentation in ckb.toml

Note:
Need to setup promethues for tor process: https://gitlab.torproject.org/tpo/onion-services/onionprobe

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code ci-runs-only: [ quick_checks,linters ]

Side effects

  • None

Release note

Title Only: Include only the PR title in the release note.

@eval-exec eval-exec force-pushed the exec/proxy branch 5 times, most recently from fe5d648 to e55f631 Compare December 5, 2024 03:37
@eval-exec
Copy link
Collaborator Author

@eval-exec eval-exec force-pushed the exec/proxy branch 10 times, most recently from de239fd to f9f0733 Compare December 24, 2024 06:15
@eval-exec eval-exec force-pushed the exec/proxy branch 3 times, most recently from 587e905 to 865759d Compare December 31, 2024 08:49
@eval-exec eval-exec force-pushed the exec/proxy branch 3 times, most recently from 260c2fe to c0f57bb Compare January 21, 2025 10:45
@eval-exec eval-exec force-pushed the exec/proxy branch 5 times, most recently from 6169766 to 12e27f6 Compare January 24, 2025 06:29
@eval-exec
Copy link
Collaborator Author

Just rebased onto develop branch.

Add Tor package installation to macOS and Windows CI workflows for Tor integration testing.
Add Go toolchain installation to macOS and Ubuntu CI workflows for building obfs4 proxy.
Add obfs4 submodule for obfuscation proxy support and Makefile targets for building obfs4proxy.
Add ckb-onion crate and torut dependency for Tor integration, and update tentacle dependencies.
Add NetworkAddresses struct to manage onion addresses alongside regular network addresses.
Add proxy module with URL validation for Tor proxy configuration and error handling.
Add onion service configuration options to network configuration for Tor integration.
Update network service builder to support proxy and onion service configuration.
Add ckb-onion crate for managing onion service integration with Tor network.
Update peer store to properly handle and store onion addresses for Tor network peers.
Update identify protocol to properly advertise and discover onion addresses for Tor network peers.
Update network state to manage public addresses including onion addresses for Tor integration.
Add onion service configuration options to network configuration and update ckb.toml template.
@eval-exec
Copy link
Collaborator Author

I removed the struct NetworkAddresses because it was unnecessary. Then I rebased onto develop branch.

Invite @driftluo @quake @zhangsoledad @doitian @chenyukang review again.

@eval-exec
Copy link
Collaborator Author

In latest commit: 48013a4

I move "tor"/"onion" related instructions from [network.proxy] to [network.onion] @quake

))
})?;
file.write_all(
&base64::engine::general_purpose::STANDARD
Copy link
Member

Choose a reason for hiding this comment

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

can we write the key as binary directly to the file, why need base64 encoding/decoding here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes we can.
I use base64 encoding/decoding, because bitcoin use base64 encoding/decoding, I followed bitcoin's style:

❯ cat ~/.bitcoin/onion_v3_private_key
ED25519-V3:aCSgwUGBquFBdiQ5S3DN3ZZ64O7tMqrtkwji7huY702sFmZNiVqsyAc4f53xF9ecDX7QrcM2PxuJePn72jFFnw==%

loop {
tokio::select! {
_ = ticker.tick() => {
let uptime = tor_controller.get_uptime().await;
Copy link
Member

Choose a reason for hiding this comment

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

it looks like you are using get_uptime as a heartbeat, since the Tor control connection is just a TCP stream, you can rely on TCP keepalive instead. Once keepalive is enabled, the OS will automatically detect when the Tor control port goes down, whether Tor crashes, restarts, or the connection drops.

Keepalive related code may be put in TorController::new.

Copy link
Collaborator Author

@eval-exec eval-exec Nov 17, 2025

Choose a reason for hiding this comment

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

it looks like you are using get_uptime as a heartbeat

Yes.

you can rely on TCP keepalive instead

If we rely solely on TCP keep-alive, we’d still need to keep reading or writing the socket to detect failure — and doing so may interfere with the Tor control-port protocol by consuming unexpected data. Hence I prefer an application-level heartbeat via tor_contoller.get_uptime().

@eval-exec
Copy link
Collaborator Author

eval-exec commented Nov 17, 2025

@quake In the latest commit: 62e959b , I added onion_external_port: u16 to [network.onion] to support configuring onion service's external port.

listen_addrs.push(Multiaddr::try_from(addr.bytes().raw_data().to_vec()).ok()?)
match Multiaddr::try_from(addr.bytes().raw_data().to_vec()) {
Ok(multi_addr) => {
listen_addrs.push(multi_addr);
Copy link
Collaborator

Choose a reason for hiding this comment

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

any specific reason for ignore this error?

Comment on lines +134 to +135
### the user should start a Tor server and set proxy_url to the Tor server's address.
### then MUST set [network.proxy.proxy_url] to tor server's address.
Copy link
Collaborator

Choose a reason for hiding this comment

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

this two line have duplicated meanning?


# [network.proxy]
### The proxy_url is user-specified SOCKS5 address, like: socks5://127.0.0.1:7891
# proxy_url = "socks5://127.0.0.1:9050"
Copy link
Collaborator

Choose a reason for hiding this comment

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

this option will be ignored if user already set onion_server?

"{} --bin {} --obfs4proxy-bin {} --port {} {}",
canonicalize_path(env::args().next().unwrap_or_else(|| "ckb-test".to_string())).display(),
canonicalize_path(global::binary()).display(),
canonicalize_path(global::obfs4proxy_binary()).display(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

have you checked out https://github.com/jmwample/ptrs ?
I'm not sure, it's just a crate and may need more investigation on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: 🏗 In progress

Development

Successfully merging this pull request may close these issues.

5 participants