Skip to content

Commit 861e15d

Browse files
authored
src/tutorials: Add hole punching tutorial (#2460)
1 parent b39770b commit 861e15d

File tree

5 files changed

+155
-4
lines changed

5 files changed

+155
-4
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ jobs:
101101
- uses: Swatinem/rust-cache@842ef286fff290e445b90b4002cc9807c3669641 # v1.3.0
102102

103103
- name: Check rustdoc links
104-
run: RUSTDOCFLAGS="--deny broken_intra_doc_links" cargo doc --verbose --workspace --no-deps --document-private-items
104+
run: RUSTDOCFLAGS="--deny broken_intra_doc_links" cargo doc --verbose --workspace --no-deps --document-private-items --all-features
105105

106106
check-clippy:
107107
runs-on: ubuntu-18.04

src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@
2424
//! [libp2p.io](https://libp2p.io/).
2525
//!
2626
//! To get started with this libp2p implementation in Rust, please take a look
27-
//! at the [`tutorial`](crate::tutorial). Further examples can be found in the
27+
//! at the [`tutorials`](crate::tutorials). Further examples can be found in the
2828
//! [examples] directory.
2929
//!
3030
//! [examples]: https://github.com/libp2p/rust-libp2p/tree/master/examples
31-
//! [ping tutorial]: https://github.com/libp2p/rust-libp2p/tree/master/examples/ping.rs
3231
3332
#![doc(html_logo_url = "https://libp2p.io/img/logo_small.png")]
3433
#![doc(html_favicon_url = "https://libp2p.io/img/favicon.png")]
@@ -151,7 +150,7 @@ pub mod bandwidth;
151150
pub mod simple;
152151

153152
#[cfg(doc)]
154-
pub mod tutorial;
153+
pub mod tutorials;
155154

156155
pub use self::core::{
157156
identity,

src/tutorials.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod hole_punching;
2+
pub mod ping;

src/tutorials/hole_punching.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// Copyright 2022 Protocol Labs.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the "Software"),
5+
// to deal in the Software without restriction, including without limitation
6+
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7+
// and/or sell copies of the Software, and to permit persons to whom the
8+
// Software is furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19+
// DEALINGS IN THE SOFTWARE.
20+
21+
//! # Hole Punching Tutorial
22+
//!
23+
//! This tutorial shows hands-on how to overcome firewalls and NATs with libp2p's hole punching
24+
//! mechanism. Before we get started, please read the [blog
25+
//! post](https://github.com/ipfs/ipfs-blog/pull/375) to familiarize yourself with libp2p's hole
26+
//! punching mechanism on a conceptual level.
27+
//!
28+
//! We will be using the [Circuit Relay v2](crate::relay::v2) and the [Direct Connection
29+
//! Upgrade through Relay (DCUtR)](crate::dcutr) protocol.
30+
//!
31+
//! You will need 3 machines for this tutorial:
32+
//!
33+
//! - A relay server
34+
//! - Any public server will do, e.g. a cloud provider VM.
35+
//! - A listening client.
36+
//! - Any computer connected to the internet, but not reachable from outside its own network,
37+
//! works.
38+
//! - This can e.g. be your friends laptop behind their router (firewall + NAT).
39+
//! - This can e.g. be some cloud provider VM, shielded from incoming connections e.g. via
40+
//! Linux's UFW on the same machine.
41+
//! - Don't use a machine that is in the same network as the dialing client. (This would require
42+
//! NAT hairpinning.)
43+
//! - A dialing client.
44+
//! - Like the above, any computer connected to the internet, but not reachable from the outside.
45+
//! - Your local machine will likely fulfill these requirements.
46+
//!
47+
//! ## Setting up the relay server
48+
//!
49+
//! Hole punching requires a public relay node for the two private nodes to coordinate their hole
50+
//! punch via. For that we need a public server somewhere in the Internet. In case you don't have
51+
//! one already, any cloud provider VM will do.
52+
//!
53+
//! Either on the server directly, or on your local machine, compile the example relay server:
54+
//!
55+
//! ``` bash
56+
//! ## Inside the rust-libp2p repository.
57+
//! cargo build --example relay_v2 -p libp2p-relay
58+
//! ```
59+
//!
60+
//! You can find the binary at `target/debug/examples/relay_v2`. In case you built it locally, copy
61+
//! it to your server.
62+
//!
63+
//! On your server, start the relay server binary:
64+
//!
65+
//! ``` bash
66+
//! ./relay_v2 --port 4001 --secret-key-seed 0
67+
//! ```
68+
//!
69+
//! Now let's make sure that the server is public, in other words let's make sure one can reach it
70+
//! through the Internet. From the dialing client:
71+
//!
72+
//! 1. Test that you can connect on Layer 3 (IP).
73+
//!
74+
//! ``` bash
75+
//! ping $RELAY_SERVER_IP
76+
//! ```
77+
//!
78+
//! 2. Test that you can connect on Layer 4 (TCP).
79+
//!
80+
//! ``` bash
81+
//! telnet $RELAY_SERVER_IP 4001
82+
//! ```
83+
//!
84+
//! 3. Test that you can connect via libp2p using [`libp2p-lookup`](https://github.com/mxinden/libp2p-lookup).
85+
//!
86+
//! ``` bash
87+
//! ## For IPv4
88+
//! libp2p-lookup direct --address /ip4/$RELAY_SERVER_IP
89+
//! ## For IPv6
90+
//! libp2p-lookup direct --address /ip6/$RELAY_SERVER_IP
91+
//! ```
92+
//!
93+
//! ## Setting up the listening client
94+
//!
95+
//! Either on the listening client machine directly, or on your local machine, compile the example
96+
//! DCUtR client:
97+
//!
98+
//! ``` bash
99+
//! ## Inside the rust-libp2p repository.
100+
//! cargo build --example client -p libp2p-dcutr
101+
//! ```
102+
//!
103+
//! You can find the binary at `target/debug/examples/client`. In case you built it locally, copy
104+
//! it to your listening client machine.
105+
//!
106+
//! On the listening client machine
107+
//!
108+
//! ``` bash
109+
//! RUST_LOG=info ./client --secret-key-seed 1 --mode listen --relay-address /dns4/$RELAY_SERVER_IP/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN
110+
//! ```
111+
//!
112+
//! Now let's make sure that the listening client is not public, in other words let's make sure one
113+
//! can not reach it directly through the Internet. From the dialing client test that you can not
114+
//! connect on Layer 4 (TCP):
115+
//!
116+
//! ``` bash
117+
//! telnet $RELAY_SERVER_IP 4001
118+
//! ```
119+
//!
120+
//! ## Connecting to the listening client from the dialing client
121+
//!
122+
//! ``` bash
123+
//! RUST_LOG=info ./client --secret-key-seed 2 --mode dial --relay-address /dns4/$RELAY_SERVER_IP/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN --remote-peer-id 12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X
124+
//! ```
125+
//!
126+
//! You should see the following logs appear:
127+
//!
128+
//! 1. The dialing client establishing a relayed connection to the listening client via the relay
129+
//! server. Note the [`/p2p-circuit` protocol](crate::multiaddr::Protocol::P2pCircuit) in the
130+
//! [`Multiaddr`](crate::Multiaddr).
131+
//!
132+
//! ``` ignore
133+
//! [2022-01-30T12:54:10Z INFO client] Established connection to PeerId("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X") via Dialer { address: "/ip4/$RELAY_PEER_ID/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN/p2p-circuit/p2p/12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X", role_override: Dialer }
134+
//! ```
135+
//!
136+
//! 2. The listening client initiating a direct connection upgrade for the new relayed connection.
137+
//! Reported by [`dcutr`](crate::dcutr) through
138+
//! [`Event::RemoteInitiatedDirectConnectionUpgrade`](crate::dcutr::behaviour::Event::RemoteInitiatedDirectConnectionUpgrade).
139+
//!
140+
//! ``` ignore
141+
//! [2022-01-30T12:54:11Z INFO client] RemoteInitiatedDirectConnectionUpgrade { remote_peer_id: PeerId("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X"), remote_relayed_addr: "/ip4/$RELAY_PEER_ID/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN/p2p-circuit/p2p/12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X" }
142+
//! ```
143+
//!
144+
//! 3. The direct connection upgrade, also known as hole punch, succeeding. Reported by
145+
//! [`dcutr`](crate::dcutr) through
146+
//! [`Event::RemoteInitiatedDirectConnectionUpgrade`](crate::dcutr::behaviour::Event::DirectConnectionUpgradeSucceeded).
147+
//!
148+
//! ``` ignore
149+
//! [2022-01-30T12:54:11Z INFO client] DirectConnectionUpgradeSucceeded { remote_peer_id: PeerId("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X") }
150+
//! ```
File renamed without changes.

0 commit comments

Comments
 (0)