Giter Site home page Giter Site logo

dennis-tra / pcp Goto Github PK

View Code? Open in Web Editor NEW
1.0K 21.0 57.0 4.23 MB

📦 Command line peer-to-peer data transfer tool based on libp2p.

License: Apache License 2.0

Go 98.97% Makefile 0.46% Ruby 0.58%
libp2p peer-to-peer cli file-sharing data-transfer pake dht mdns ipfs hacktoberfest

pcp's Introduction

pcp - Peer Copy

standard-readme compliant Go Report Card Maintainability Latest test suite run result Github Releases Download Count

Command line peer-to-peer data transfer tool based on libp2p.

Demo animation

This tool was published at the IFIP 2021 conference. You can find the preprint below.

Table of Contents

Motivation

There already exists a long list of file transfer tools (see Related Efforts), so why bother building another one? The problem I had with the existing tools is that they rely on a limited set of servers to orchestrate peer matching and data relaying which poses a centralisation concern. Many of the usual centralisation vs. decentralisation arguments apply here, e.g. the servers are single points of failures, the service operator has the power over whom to serve and whom not, etc. Further, as this recent issue in croc shows, this is a real risk for sustainable operation of the provided service.

Project Status

The tool is in a very early stage, and I'm aware of performance, usability and security issues. Don't use it for anything serious. Although I criticised tools like magic-wormhole or croc above, they are amazing and way more mature.

There are also drawbacks with this approach: It's slower than established centralised methods if you want to transmit data across network boundaries. A DHT query to find your peer can easily take several minutes. Further, the bandwidth and geographic location of a potential relaying peer is not guaranteed which can lead to long transmission times.

How does it work?

When running pcp send you'll see four random words from a list of the Bitcoin improvement proposal BIP39. There are lists in nine different languages of 2048 words each, currently only english is supported. The first word is interpreted as a channel ID in the range from 0 to 2047. pcp advertises the identifier /pcp/{unix-timestamp}/{channel-id} in its local network via mDNS and a hashed version of this string in the DHT of IPFS. The unix timestamp is the current time truncated to 5 minutes and the prefix /pcp is the protocol prefix. In the future: When you enter a new 5-minute interval while pcp send is running it advertises an updated identifier.

To receive the file your peer enters pcp receive four-words-from-above and pcp uses the first word together with the current time truncated to 5 minutes to find the sending peer in the DHT and in your local network via mDNS. It also searches for an identifier of the previous 5-minute interval. As soon as the peer is found, both do a password authenticated key exchange (PAKE) to authenticate each other. In this procedure a comparably weak password (four-words-from-above) gets replaced with a strong session key that is used to encrypt all future communication. The default TLS encryption that libp2p provides is not sufficient in this case as we could still, in theory, talk to a wrong peer - just encrypted.

After the peer is authenticated the receiver must confirm the file transfer, and the file gets transmitted.

Usage

The sending peer runs:

$ pcp send my_file
Code is:  bubble-enemy-result-increase
On the other machine run:
	pcp receive bubble-enemy-result-increase

The receiving peer runs:

$ pcp receive bubble-enemy-result-increase
Looking for peer bubble-enemy-result-increase...

If you're on different networks the lookup can take quite long (~ 2-3 minutes). Currently, there is no output while both parties are working on peer discovery, so just be very patient.

Install

Package managers

brew install pcp

It's on the roadmap to also distribute pcp via apt, yum, scoop and more ...

Release download

Head over to the releases and download the latest archive for your platform.

From source

To compile it yourself run:

go install github.com/dennis-tra/pcp/cmd/pcp@latest # Go 1.13 or higher is required

Make sure the $GOPATH/bin is in your PATH variable to access the installed pcp executable.

Development

Protobuf definitions

First install the protoc compiler:

make tools # downloads gofumpt and protoc
make proto # generates protobuf

The current proto definitions were generated with libprotoc 3.14.0.

Feature Roadmap

Shamelessly copied from croc:

  • allows any two computers to transfer data (using a relay)
  • provides end-to-end encryption (using PAKE)
    • ✅ yup, it uses pake/v2 from croc
  • enables easy cross-platform transfers (Windows, Linux, Mac)
    • ✅ Linux <-> Mac, ❌ Windows, but it's planned!
  • allows multiple file transfers
    • ✅ it allows transferring directories
  • allows resuming transfers that are interrupted
    • ❌ not yet
  • local server or port-forwarding not needed
  • ipv6-first with ipv4 fallback
  • can use proxy, like tor
    • ❌ not yet

You can find a project plan in the project tab of this page. Some other ideas I would love to work on include:

  • browser interop via the means of js-libp2p
  • experimental decentralised NAT hole punching via DHT signaling servers - Project Flare

Related Efforts

  • croc - Easily and securely send things from one computer to another
  • magic-wormhole - get things from one computer to another, safely
  • dcp - Remote file copy, powered by the Dat protocol.
  • iwant - CLI based decentralized peer to peer file sharing
  • p2pcopy - Small command line application to do p2p file copy behind firewalls without a central server.
  • zget - Filename based peer to peer file transfer
  • sharedrop - Easy P2P file transfer powered by WebRTC - inspired by Apple AirDrop
  • filepizza - Peer-to-peer file transfers in your browser
  • toss - Dead simple LAN file transfers from the command line
  • Forgot yours? Open an issue or submit a PR :)

Maintainers

@dennis-tra.

Acknowledgments

  • go-libp2p - The Go implementation of the libp2p Networking Stack.
  • pake/v2 - PAKE library for generating a strong secret between parties over an insecure channel
  • progressbar - A really basic thread-safe progress bar for Golang applications

Contributing

Feel free to dive in! Open an issue or submit PRs.

Research

This tool was submitted to the International Federation for Information Processing 2021 (IFIP '21) conference and accepted for publication. You can find the preprint here.

Cite the paper with this BibTeX entry: Jesse Pinkman
@inproceedings{Trautwein2021,
  title        = {Introducing Peer Copy - A Fully Decentralized Peer-to-Peer File Transfer Tool},
  author       = {Trautwein, Dennis and Schubotz, Moritz and Gipp, Bela},
  year         = 2021,
  month        = {June},
  booktitle    = {2021 IFIP Networking Conference (IFIP Networking)},
  publisher    = {IEEE},
  address      = {Espoo and Helsinki, Finland},
  doi          = {10.23919/IFIPNetworking52078.2021.9472842},
  note         = {ISBN 978-3-9031-7639-3},
  topic        = {misc}
}

Support

It would really make my day if you supported this project through Buy Me A Coffee.

Other Projects

You may be interested in one of my other projects:

  • image-stego - A novel way to image manipulation detection. Steganography-based image integrity - Merkle tree nodes embedded into image chunks so that each chunk's integrity can be verified on its own.
  • nebula-crawler - A libp2p DHT crawler that also monitors the liveness and availability of peers. 🏆 Winner of the DI2F Workshop Hackathon 🏆

License

Apache License Version 2.0 © Dennis Trautwein

pcp's People

Contributors

dennis-tra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pcp's Issues

Issue on Windows 11

Calculating on key information...panic: crypto/elliptic: Add was called on an invalid point

goroutine 7213 [running]:
crypto/elliptic.(*nistCurve[...]).Add(0x15cb340?, 0xa3b9d2, 0x68?, 0x11680a0?, 0xc00102c201?)
        C:/Program Files/Go/src/crypto/elliptic/nistec.go:181 +0xb5
github.com/schollz/pake/v2.(*Pake).Update(0xc0011ac360, {0xc001ec2000, 0x645, 0x645})
        C:/Users/micro/go/pkg/mod/github.com/schollz/pake/[email protected]/pake.go:236 +0xbd7
github.com/dennis-tra/pcp/pkg/node.(*PakeProtocol).StartKeyExchange(0xc0000e02a0, {0x15bed78, 0xc00008ccd0}, {0xc00141c0c0, 0x27})
        C:/Users/micro/Downloads/pcp/pkg/node/pake.go:250 +0x357
github.com/dennis-tra/pcp/pkg/receive.(*Node).HandlePeer(0xc00063c990, {{0xc00141c0c0, 0x27}, {0xc001944b10, 0x1, 0x1}})
        C:/Users/micro/Downloads/pcp/pkg/receive/node.go:157 +0x525
created by github.com/dennis-tra/pcp/pkg/mdns.(*Discoverer).drainEntriesChan
        C:/Users/micro/Downloads/pcp/pkg/mdns/discoverer.go:82 +0x29b

Any ideas on how to solve this?

Simplify language

Dear @dennis-tra, consider providing alternative for receive (or is it recieve, or recive?) command.
Simple get seems to work much better for those folks like me whose native language is not English,
or even omit this step (as croc does) with even simpler pcp <code>.

Weird crash on macOS 13.5.2, go 1.21.1

In installed it under macos 13.5.2, go 1.21.1 with the command "go install github.com/dennis-tra/pcp/cmd/pcp@latest", and ran it like this:

$ pcp send db-pids.txt

The output was

Code is: w1-w2-w3-w4
On the other machine run:
pcp receive w1-w2-w3-w4
runtime: g85: frame.sp=0xc0001c36b8 top=0xc0001c3fe0
stack=[0xc0001c2000-0xc0001c4000
fatal error: traceback did not unwind completely

runtime stack:
runtime.throw({0x19499ad?, 0x0?})
/usr/local/go/src/runtime/panic.go:1077 +0x5c fp=0x700011bd49d8 sp=0x700011bd49a8 pc=0x1038e1c
runtime.(*unwinder).finishInternal(0x0?)
/usr/local/go/src/runtime/traceback.go:561 +0x12a fp=0x700011bd4a18 sp=0x700011bd49d8 pc=0x105d76a
runtime.(*unwinder).next(0x700011bd4c18?)
/usr/local/go/src/runtime/traceback.go:442 +0x232 fp=0x700011bd4a90 sp=0x700011bd4a18 pc=0x105d572
runtime.copystack(0xc00018b6c0, 0x800000002?)
/usr/local/go/src/runtime/stack.go:934 +0x2d2 fp=0x700011bd4d88 sp=0x700011bd4a90 pc=0x10522d2
runtime.newstack()
/usr/local/go/src/runtime/stack.go:1116 +0x47f fp=0x700011bd4f38 sp=0x700011bd4d88 pc=0x105287f
runtime.morestack()
/usr/local/go/src/runtime/asm_amd64.s:593 +0x8f fp=0x700011bd4f40 sp=0x700011bd4f38 pc=0x1069f6f

goroutine 85 [copystack]:
github.com/minio/sha256-simd.blockAvx2({0xc0001c36f0, 0x8, 0x8}, {0xc0001c3778, 0x40, 0x40})
/Users/theo/work/go/pkg/mod/github.com/minio/[email protected]/sha256blockAvx2_amd64.s:125 +0x1423 fp=0xc0001c36c0 sp=0xc0001c36b8 pc=0x11d7dc3
created by github.com/libp2p/go-libp2p-kad-dht/rtrefresh.(*RtRefreshManager).Start in goroutine 105
/Users/theo/work/go/pkg/mod/github.com/libp2p/[email protected]/rtrefresh/rt_refresh_manager.go:88 +0x65

Plus a lot more stacks.

Attempting to send a file kills the entire network

(c) 2020 Microsoft Corporation. All rights reserved.

C:\Users\\Downloads\pcp_0.3.3_windows_amd64>ping google.com

Pinging google.com [216.58.212.238] with 32 bytes of data:
Reply from 216.58.212.238: bytes=32 time=17ms TTL=116
Reply from 216.58.212.238: bytes=32 time=24ms TTL=116
Reply from 216.58.212.238: bytes=32 time=16ms TTL=116

Ping statistics for 216.58.212.238:
    Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 16ms, Maximum = 24ms, Average = 19ms
Control-C
^C
C:\Users\\Downloads\pcp_0.3.3_windows_amd64>pcp send test.txt
Code is:  tag-draw-absent-track
On the other machine run:
        pcp receive tag-draw-absent-track
Stopping...

C:\Users\\Downloads\pcp_0.3.3_windows_amd64>ping google.com

Pinging google.com [216.58.212.238] with 32 bytes of data:
Request timed out.
Request timed out.

Ping statistics for 216.58.212.238:
    Packets: Sent = 2, Received = 0, Lost = 2 (100% loss),
Control-C
^C
C:\Users\\Downloads\pcp_0.3.3_windows_amd64

The debug output above provides all the relevant version information, and the internet also goes down for all the other devices on my network (in fact, the SSID disappears for a while). I can provide a network diagram if necessary, but my router is an ISP-issued Virgin Media Hub 3.

never made it to transfer file in my home LAN

I use one Win10 machine to send file then use another mac to receive but never made it work. Wondering if something I missed.

Win10 side output:

pcp.exe send '.\Downloads\Telegram Desktop\2018-09-01.pdf' Code is:  sweet-curve-gym-rigid On the other machine run:        pcp receive sweet-curve-gym-rigid could not establish enough connections to bootstrap peers        failed to dial QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt: no good addresses        failed to dial QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa: all dials failed  * [/ip6/2604:1380:0:c100::1/tcp/4001] dial tcp6 [2604:1380:0:c100::1]:4001: connectex: A socket operation was attempted to an unreachable network.  * [/ip4/147.75.77.187/tcp/4001] dial tcp4 0.0.0.0:65322->147.75.77.187:4001: i/o timeout        failed to dial QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb: all dials failed  * [/ip4/147.75.83.83/tcp/4001] dial tcp4 0.0.0.0:65322->147.75.83.83:4001: i/o timeout        failed to dial QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN: all dials failed  * [/ip6/2604:1380:1000:6000::1/tcp/4001] dial tcp6 [2604:1380:1000:6000::1]:4001: connectex: A socket operation was attempted to an unreachable network.  * [/ip4/147.75.109.213/tcp/4001] failed to negotiate stream multiplexer: read tcp4 192.168.1.69:65322->147.75.109.213:4001: wsarecv: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.        failed to dial QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ: all dials failed  * [/ip4/104.131.131.82/tcp/4001] failed to negotiate stream multiplexer: read tcp4 192.168.1.69:65322->104.131.131.82:4001: wsarecv: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. this means you will only be able to transfer files in your local network

Mac side output:

Looking for peer sweet-curve-gym-rigid...
could not establish enough connections to bootstrap peers
failed to dial QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb: no good addresses
failed to dial QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt: all dials failed
 * [/ip6/2604:1380:3000:1f00::1/tcp/4001] dial tcp6 [2604:1380:3000:1f00::1]:4001: connect: no route to host
failed to dial QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ: all dials failed
 * [/ip4/104.131.131.82/tcp/4001] dial tcp4 0.0.0.0:59217->104.131.131.82:4001: i/o timeout
failed to dial QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa: all dials failed
 * [/ip6/2604:1380:0:c100::1/tcp/4001] dial tcp6 [2604:1380:0:c100::1]:4001: connect: no route to host
context deadline exceeded
this means you will only be able to transfer files in your local network

Attempting to transfer a directory error does not exit on the receiving peer

First of all, I fucking love the simplicity of this app. I just transferred some files between two computers and it was so simple. Thank you for making it.


On the sending side, the peers connect and authenticate, then I get the error:

Peer connected and authenticated!
Error transferring file read BraveSoftware: is a directory

Then, the sending side exits.

On the receiving side, I receive no error.

Looking for peer camp-match-exhaust-fire...
Peer connected and authenticated!

and it does not close.

It seems the following behavior should be expected:

  1. pcp should either wrap/compress/file-ify the folder before sending (and unwrap it on the receiving side)
  2. pcp should throw an error as soon as it sees the input is a folder, before it connects and authenticates to the peer.

Very low transfer speed

We both have a stable 100 Mbps internet but pcp sends it with about 2.3 MB/s. Does it use multiple threads? I'm using v0.4.0-rc1 Windows.

[Fedora 33] Installation via .rpm written over during system upgrade

When upgrading the system using the command sudo dnf upgrade, the pcp package is written over by this package

Last metadata expiration check: 5:27:05 ago on Fri 12 Mar 2021 07:59:14 PM EST.
Available Packages
Name         : pcp
Version      : 5.2.5
Release      : 2.fc33
Architecture : x86_64
Size         : 1.3 M
Source       : pcp-5.2.5-2.fc33.src.rpm
Repository   : updates
Summary      : System-level performance monitoring and performance management
URL          : https://pcp.io
License      : GPLv2+ and LGPLv2+ and CC-BY
Description  : Performance Co-Pilot (PCP) provides a framework and services to
             : support system-level performance monitoring and performance
             : management.
             : 
             : The PCP open source release provides a unifying abstraction for
             : all of the interesting performance data in a system, and allows
             : client applications to easily retrieve and process any subset of
             : that data.

which renders this pcp no longer accessible or installed (not quite sure what happens to the package).
Current workaround is to uninstall that pcp using sudo dnf remove pcp and then re-install this pcp with standard software installation from either command line of Gnome software.

Perhaps changing the distribution name of this package to something along the lines of pcp-filetransfer (?) would fix this issue, at least on Fedora.

Installation cannot find packages

I might just be misunderstanding some basic gopath type thing, but I run into errors when attempting to follow the installation instructions:

$ go install cmd/pcp/pcp.go
cmd/pcp/pcp.go:9:2: cannot find package "github.com/dennis-tra/pcp/internal/log" in any of:
	/usr/lib/go-1.10/src/github.com/dennis-tra/pcp/internal/log (from $GOROOT)
	/home/lacker/go/src/github.com/dennis-tra/pcp/internal/log (from $GOPATH)
cmd/pcp/pcp.go:10:2: cannot find package "github.com/dennis-tra/pcp/pkg/initialize" in any of:
	/usr/lib/go-1.10/src/github.com/dennis-tra/pcp/pkg/initialize (from $GOROOT)
	/home/lacker/go/src/github.com/dennis-tra/pcp/pkg/initialize (from $GOPATH)
cmd/pcp/pcp.go:11:2: cannot find package "github.com/dennis-tra/pcp/pkg/receive" in any of:
	/usr/lib/go-1.10/src/github.com/dennis-tra/pcp/pkg/receive (from $GOROOT)
	/home/lacker/go/src/github.com/dennis-tra/pcp/pkg/receive (from $GOPATH)
cmd/pcp/pcp.go:12:2: cannot find package "github.com/dennis-tra/pcp/pkg/send" in any of:
	/usr/lib/go-1.10/src/github.com/dennis-tra/pcp/pkg/send (from $GOROOT)
	/home/lacker/go/src/github.com/dennis-tra/pcp/pkg/send (from $GOPATH)
cmd/pcp/pcp.go:7:2: cannot find package "github.com/urfave/cli/v2" in any of:
	/usr/lib/go-1.10/src/github.com/urfave/cli/v2 (from $GOROOT)
	/home/lacker/go/src/github.com/urfave/cli/v2 (from $GOPATH)

could not establish enough connections to bootstrap peers; BUT I can ping them

when I run pcp send command, the output is like :

could not establish enough connections to bootstrap peers
	failed to dial QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ: all dials failed
  * [/ip4/104.131.131.82/tcp/4001] dial tcp4 0.0.0.0:38687->104.131.131.82:4001: i/o timeout
	failed to dial QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb: all dials failed
  * [/ip6/2604:1380:2000:7a00::1/tcp/4001] dial tcp6 [2604:1380:2000:7a00::1]:4001: connect: network is unreachable
  * [/ip4/147.75.83.83/tcp/4001] dial tcp4 0.0.0.0:38687->147.75.83.83:4001: i/o timeout
	failed to dial QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN: all dials failed
  * [/ip6/2604:1380:1000:6000::1/tcp/4001] dial tcp6 [2604:1380:1000:6000::1]:4001: connect: network is unreachable
  * [/ip4/147.75.109.213/tcp/4001] dial tcp4 0.0.0.0:38687->147.75.109.213:4001: i/o timeout
this means you will only be able to transfer files in your local network


But I can ping these IP Address ping 104.131.131.82, ping 147.75.109.213
Which means the network between me and the bootstrap peers is reachable.

PING 147.75.109.213 (147.75.109.213) type `Ctrl-C` to abort
 seq=0 32bytes from 147.75.109.213: ttl=46 time=217.729074ms
 seq=1 32bytes from 147.75.109.213: ttl=46 time=217.792354ms
 seq=2 32bytes from 147.75.109.213: ttl=46 time=217.940214ms
 seq=3 32bytes from 147.75.109.213: ttl=46 time=217.733247ms
───────── 147.75.109.213 ping statistics ─────────
PACKET STATISTICS: 4 transmitted => 4 received (0% loss)
ROUND TRIP: min=217.729074ms avg=217.798722ms max=217.940214ms stddev=85.437µs

So is this issue caused by my network or the network between me and the bootstrap peer or the DHT?

I really want to try this project, it looks fun and inspiring

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.