From 861e15dabbba28ce5aff3c6332ab10ce9c4c24b8 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 10 Feb 2022 16:36:20 +0100 Subject: [PATCH] src/tutorials: Add hole punching tutorial (#2460) --- .github/workflows/ci.yml | 2 +- src/lib.rs | 5 +- src/tutorials.rs | 2 + src/tutorials/hole_punching.rs | 150 +++++++++++++++++++++++++ src/{tutorial.rs => tutorials/ping.rs} | 0 5 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/tutorials.rs create mode 100644 src/tutorials/hole_punching.rs rename src/{tutorial.rs => tutorials/ping.rs} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e6a51d4af0..3bf167db8f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,7 +101,7 @@ jobs: - uses: Swatinem/rust-cache@842ef286fff290e445b90b4002cc9807c3669641 # v1.3.0 - name: Check rustdoc links - run: RUSTDOCFLAGS="--deny broken_intra_doc_links" cargo doc --verbose --workspace --no-deps --document-private-items + run: RUSTDOCFLAGS="--deny broken_intra_doc_links" cargo doc --verbose --workspace --no-deps --document-private-items --all-features check-clippy: runs-on: ubuntu-18.04 diff --git a/src/lib.rs b/src/lib.rs index dbfe64cb43a..2cf70fd9be4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,11 +24,10 @@ //! [libp2p.io](https://libp2p.io/). //! //! To get started with this libp2p implementation in Rust, please take a look -//! at the [`tutorial`](crate::tutorial). Further examples can be found in the +//! at the [`tutorials`](crate::tutorials). Further examples can be found in the //! [examples] directory. //! //! [examples]: https://github.com/libp2p/rust-libp2p/tree/master/examples -//! [ping tutorial]: https://github.com/libp2p/rust-libp2p/tree/master/examples/ping.rs #![doc(html_logo_url = "https://libp2p.io/img/logo_small.png")] #![doc(html_favicon_url = "https://libp2p.io/img/favicon.png")] @@ -151,7 +150,7 @@ pub mod bandwidth; pub mod simple; #[cfg(doc)] -pub mod tutorial; +pub mod tutorials; pub use self::core::{ identity, diff --git a/src/tutorials.rs b/src/tutorials.rs new file mode 100644 index 00000000000..fd7f319fc7e --- /dev/null +++ b/src/tutorials.rs @@ -0,0 +1,2 @@ +pub mod hole_punching; +pub mod ping; diff --git a/src/tutorials/hole_punching.rs b/src/tutorials/hole_punching.rs new file mode 100644 index 00000000000..3c24c61ebf0 --- /dev/null +++ b/src/tutorials/hole_punching.rs @@ -0,0 +1,150 @@ +// Copyright 2022 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +//! # Hole Punching Tutorial +//! +//! This tutorial shows hands-on how to overcome firewalls and NATs with libp2p's hole punching +//! mechanism. Before we get started, please read the [blog +//! post](https://github.com/ipfs/ipfs-blog/pull/375) to familiarize yourself with libp2p's hole +//! punching mechanism on a conceptual level. +//! +//! We will be using the [Circuit Relay v2](crate::relay::v2) and the [Direct Connection +//! Upgrade through Relay (DCUtR)](crate::dcutr) protocol. +//! +//! You will need 3 machines for this tutorial: +//! +//! - A relay server +//! - Any public server will do, e.g. a cloud provider VM. +//! - A listening client. +//! - Any computer connected to the internet, but not reachable from outside its own network, +//! works. +//! - This can e.g. be your friends laptop behind their router (firewall + NAT). +//! - This can e.g. be some cloud provider VM, shielded from incoming connections e.g. via +//! Linux's UFW on the same machine. +//! - Don't use a machine that is in the same network as the dialing client. (This would require +//! NAT hairpinning.) +//! - A dialing client. +//! - Like the above, any computer connected to the internet, but not reachable from the outside. +//! - Your local machine will likely fulfill these requirements. +//! +//! ## Setting up the relay server +//! +//! Hole punching requires a public relay node for the two private nodes to coordinate their hole +//! punch via. For that we need a public server somewhere in the Internet. In case you don't have +//! one already, any cloud provider VM will do. +//! +//! Either on the server directly, or on your local machine, compile the example relay server: +//! +//! ``` bash +//! ## Inside the rust-libp2p repository. +//! cargo build --example relay_v2 -p libp2p-relay +//! ``` +//! +//! You can find the binary at `target/debug/examples/relay_v2`. In case you built it locally, copy +//! it to your server. +//! +//! On your server, start the relay server binary: +//! +//! ``` bash +//! ./relay_v2 --port 4001 --secret-key-seed 0 +//! ``` +//! +//! Now let's make sure that the server is public, in other words let's make sure one can reach it +//! through the Internet. From the dialing client: +//! +//! 1. Test that you can connect on Layer 3 (IP). +//! +//! ``` bash +//! ping $RELAY_SERVER_IP +//! ``` +//! +//! 2. Test that you can connect on Layer 4 (TCP). +//! +//! ``` bash +//! telnet $RELAY_SERVER_IP 4001 +//! ``` +//! +//! 3. Test that you can connect via libp2p using [`libp2p-lookup`](https://github.com/mxinden/libp2p-lookup). +//! +//! ``` bash +//! ## For IPv4 +//! libp2p-lookup direct --address /ip4/$RELAY_SERVER_IP +//! ## For IPv6 +//! libp2p-lookup direct --address /ip6/$RELAY_SERVER_IP +//! ``` +//! +//! ## Setting up the listening client +//! +//! Either on the listening client machine directly, or on your local machine, compile the example +//! DCUtR client: +//! +//! ``` bash +//! ## Inside the rust-libp2p repository. +//! cargo build --example client -p libp2p-dcutr +//! ``` +//! +//! You can find the binary at `target/debug/examples/client`. In case you built it locally, copy +//! it to your listening client machine. +//! +//! On the listening client machine +//! +//! ``` bash +//! RUST_LOG=info ./client --secret-key-seed 1 --mode listen --relay-address /dns4/$RELAY_SERVER_IP/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN +//! ``` +//! +//! Now let's make sure that the listening client is not public, in other words let's make sure one +//! can not reach it directly through the Internet. From the dialing client test that you can not +//! connect on Layer 4 (TCP): +//! +//! ``` bash +//! telnet $RELAY_SERVER_IP 4001 +//! ``` +//! +//! ## Connecting to the listening client from the dialing client +//! +//! ``` bash +//! RUST_LOG=info ./client --secret-key-seed 2 --mode dial --relay-address /dns4/$RELAY_SERVER_IP/tcp/4001/p2p/12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN --remote-peer-id 12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X +//! ``` +//! +//! You should see the following logs appear: +//! +//! 1. The dialing client establishing a relayed connection to the listening client via the relay +//! server. Note the [`/p2p-circuit` protocol](crate::multiaddr::Protocol::P2pCircuit) in the +//! [`Multiaddr`](crate::Multiaddr). +//! +//! ``` ignore +//! [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 } +//! ``` +//! +//! 2. The listening client initiating a direct connection upgrade for the new relayed connection. +//! Reported by [`dcutr`](crate::dcutr) through +//! [`Event::RemoteInitiatedDirectConnectionUpgrade`](crate::dcutr::behaviour::Event::RemoteInitiatedDirectConnectionUpgrade). +//! +//! ``` ignore +//! [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" } +//! ``` +//! +//! 3. The direct connection upgrade, also known as hole punch, succeeding. Reported by +//! [`dcutr`](crate::dcutr) through +//! [`Event::RemoteInitiatedDirectConnectionUpgrade`](crate::dcutr::behaviour::Event::DirectConnectionUpgradeSucceeded). +//! +//! ``` ignore +//! [2022-01-30T12:54:11Z INFO client] DirectConnectionUpgradeSucceeded { remote_peer_id: PeerId("12D3KooWPjceQrSwdWXPyLLeABRXmuqt69Rg3sBYbU1Nft9HyQ6X") } +//! ``` diff --git a/src/tutorial.rs b/src/tutorials/ping.rs similarity index 100% rename from src/tutorial.rs rename to src/tutorials/ping.rs