diff --git a/.gitignore b/.gitignore index 6ddb6f6..d4b9b55 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.exe -peerguard* +pgcli-* +pgserve-* wintun/ *.zip *.dll diff --git a/Makefile b/Makefile index 8892e81..0be396f 100644 --- a/Makefile +++ b/Makefile @@ -6,9 +6,11 @@ GOBUILD := CGO_ENABLED=0 go build -ldflags "-s -w -X 'main.Version=${version}' - all: linux windows darwin linuxamd64: - GOOS=linux GOARCH=amd64 ${GOBUILD} -o peerguard-${version}-linux-amd64 + GOOS=linux GOARCH=amd64 ${GOBUILD} -o pgcli-${version}-linux-amd64 ./cmd/pgcli + GOOS=linux GOARCH=amd64 ${GOBUILD} -o pgserve-${version}-linux-amd64 ./cmd/pgserve linuxarm64: - GOOS=linux GOARCH=arm64 ${GOBUILD} -o peerguard-${version}-linux-arm64 + GOOS=linux GOARCH=arm64 ${GOBUILD} -o pgcli-${version}-linux-arm64 ./cmd/pgcli + GOOS=linux GOARCH=arm64 ${GOBUILD} -o pgserve-${version}-linux-arm64 ./cmd/pgserve linux: linuxamd64 linuxarm64 wintun: @@ -16,33 +18,35 @@ wintun: unzip wintun-0.14.1.zip rm wintun-0.14.1.zip winamd64: wintun - GOOS=windows GOARCH=amd64 ${GOBUILD} -o peerguard-${version}-windows-amd64.exe + GOOS=windows GOARCH=amd64 ${GOBUILD} -o pgcli-${version}-windows-amd64.exe ./cmd/pgcli cp wintun/bin/amd64/wintun.dll . - zip -r peerguard-${version}-windows-amd64.zip peerguard-${version}-windows-amd64.exe wintun.dll + zip -r pgcli-${version}-windows-amd64.zip pgcli-${version}-windows-amd64.exe wintun.dll rm wintun.dll winarm64: wintun - GOOS=windows GOARCH=arm64 ${GOBUILD} -o peerguard-${version}-windows-arm64.exe + GOOS=windows GOARCH=arm64 ${GOBUILD} -o pgcli-${version}-windows-arm64.exe ./cmd/pgcli cp wintun/bin/arm64/wintun.dll . - zip -r peerguard-${version}-windows-arm64.zip peerguard-${version}-windows-arm64.exe wintun.dll + zip -r pgcli-${version}-windows-arm64.zip pgcli-${version}-windows-arm64.exe wintun.dll rm wintun.dll windows: winamd64 winarm64 darwinamd64: - GOOS=darwin GOARCH=amd64 ${GOBUILD} -o peerguard-${version}-darwin-amd64 + GOOS=darwin GOARCH=amd64 ${GOBUILD} -o pgcli-${version}-darwin-amd64 ./cmd/pgcli darwinarm64: - GOOS=darwin GOARCH=arm64 ${GOBUILD} -o peerguard-${version}-darwin-arm64 + GOOS=darwin GOARCH=arm64 ${GOBUILD} -o pgcli-${version}-darwin-arm64 ./cmd/pgcli darwin: darwinamd64 darwinarm64 github: clean all - gzip peerguard-${version}-linux* - gzip peerguard-${version}-darwin* + gzip pgcli-${version}-linux* + gzip pgcli-${version}-darwin* + gzip pgserve-${version}-linux* git tag -d ${version} 2>/dev/null || true gh release delete ${version} -y --cleanup-tag 2>/dev/null || true - gh release create ${version} --generate-notes --title "peerguard ${version}" peerguard-${version}*.gz peerguard-${version}*.zip + gh release create ${version} --generate-notes --title "peerguard ${version}" pgcli-${version}*.gz pgcli-${version}*.zip pgserve-${version}*.gz dist: github clean: - rm peerguard* 2>/dev/null || true + rm pgcli* 2>/dev/null || true + rm pgserve* 2>/dev/null || true rm *.zip 2>/dev/null || true rm *.dll 2>/dev/null || true diff --git a/README.md b/README.md index 67ef7c9..087121a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,31 @@ -## Example +# PeerGuard - Another p2p network library in Go -### 1. Code +## Get Started -#### Peer1 (act as echo server) +### Deploy the peermap server +#### 1. Run the pgserve daemon +``` +$ pgserve -l 127.0.0.1:9987 --secret-key 5172554832d76672d1959a5ac63c5ab9 \ + --stun stun.qq.com:3478 --stun stun.miwifi.com:3478 +``` + +#### 2. Wrap pgserve as an https server +``` +$ caddy reverse-proxy --from https://synf.in/pg --to 127.0.0.1:9987 +``` + +### Follow the steps below to run VPN nodes in different networks +#### 1. Generate a network secret +``` +# pgcli secret --secret-key 5172554832d76672d1959a5ac63c5ab9 > ~/.peerguard_network_secret.json +``` +#### 2. Run a VPN daemon +``` +# pgcli vpn -s wss://synf.in/pg --ipv4 100.64.0.1/24 --ipv6 fd00::1/64 +``` + +## P2P programming example +### Peer1 (act as echo server) ```go peermap := p2p.Peermap("wss://synf.in/pg") @@ -11,13 +34,14 @@ if err != nil { panic(err) } fmt.Println(intent.AuthURL()) // https://synf.in/oidc/google?state=5G68CtYnMRMdrtrRF -secret, err := intent.Wait(context.TODO()) +networkSecret, err := intent.Wait(context.TODO()) if err != nil { panic(err) } packetConn, err := p2p.ListenPacket( - &secret, peermap, + &networkSecret, + peermap, p2p.ListenPeerID("uniqueString"), // any unique string (less than 256bytes) ) if err != nil { @@ -39,11 +63,11 @@ for { } ``` -#### Peer2 +### Peer2 ```go ... -packetConn, err := p2p.ListenPacket(secret.Secret, peermap) +packetConn, err := p2p.ListenPacket(&networkSecret, peermap) if err != nil { panic(err) } @@ -65,31 +89,3 @@ if err !=nil { } fmt.Println(peerID, ":", string(buf[:n])) // uniqueString : hello ``` - -### 2. VPN(p2p) - -#### Machine 1 -``` -# peerguard vpn --peermap wss://synf.in/pg --ipv4 100.64.0.1/24 --ipv6 fd00::1/64 -``` - -#### Machine 2 -``` -# peerguard vpn --peermap wss://synf.in/pg --ipv4 100.64.0.2/24 --ipv6 fd00::2/64 -``` -**Another terminal on machine 2** -``` -# ping 100.64.0.1 -PING 100.64.0.1 (100.64.0.1) 56(84) bytes of data. -64 bytes from 100.64.0.1: icmp_seq=1 ttl=64 time=7.88 ms -64 bytes from 100.64.0.1: icmp_seq=2 ttl=64 time=4.19 ms -64 bytes from 100.64.0.1: icmp_seq=3 ttl=64 time=4.47 ms -64 bytes from 100.64.0.1: icmp_seq=4 ttl=64 time=4.54 ms -... -# ping fd00::1 -PING fd00::1 (fd00::1) 56 data bytes -64 bytes from fd00::1: icmp_seq=1 ttl=64 time=4.29 ms -64 bytes from fd00::1: icmp_seq=2 ttl=64 time=5.84 ms -64 bytes from fd00::1: icmp_seq=3 ttl=64 time=3.48 ms -64 bytes from fd00::1: icmp_seq=4 ttl=64 time=4.69 ms -``` diff --git a/cmd/curve25519/curve25519.go b/cmd/pgcli/curve25519/curve25519.go similarity index 100% rename from cmd/curve25519/curve25519.go rename to cmd/pgcli/curve25519/curve25519.go diff --git a/main.go b/cmd/pgcli/main.go similarity index 55% rename from main.go rename to cmd/pgcli/main.go index eaed1c8..472e450 100644 --- a/main.go +++ b/cmd/pgcli/main.go @@ -4,10 +4,9 @@ import ( "fmt" "log/slog" - "github.com/rkonfj/peerguard/cmd/curve25519" - "github.com/rkonfj/peerguard/cmd/serve" - "github.com/rkonfj/peerguard/cmd/token" - "github.com/rkonfj/peerguard/cmd/vpn" + "github.com/rkonfj/peerguard/cmd/pgcli/curve25519" + "github.com/rkonfj/peerguard/cmd/pgcli/secret" + "github.com/rkonfj/peerguard/cmd/pgcli/vpn" "github.com/spf13/cobra" ) @@ -18,12 +17,12 @@ var ( func main() { cmd := &cobra.Command{ - Use: "peerguard", + Use: "pgcli", Version: fmt.Sprintf("%s, commit %s", Version, Commit), - Short: "A peer to peer network toolset", + Short: "A p2p network toolset", SilenceUsage: true, PersistentPreRunE: func(cmd *cobra.Command, args []string) error { - verbose, err := cmd.Flags().GetInt("v") + verbose, err := cmd.Flags().GetInt("verbose") if err != nil { return err } @@ -32,12 +31,10 @@ func main() { }, } - cmd.AddCommand(serve.Cmd) - cmd.AddCommand(token.Cmd) cmd.AddCommand(vpn.Cmd) + cmd.AddCommand(secret.Cmd) cmd.AddCommand(curve25519.Cmd) - cmd.PersistentFlags().Int("v", 0, "logger verbosity level") - + cmd.PersistentFlags().IntP("verbose", "V", 0, "logger verbosity level") cmd.Execute() } diff --git a/cmd/token/token.go b/cmd/pgcli/secret/secret.go similarity index 79% rename from cmd/token/token.go rename to cmd/pgcli/secret/secret.go index b0cfb3a..0671f46 100644 --- a/cmd/token/token.go +++ b/cmd/pgcli/secret/secret.go @@ -1,4 +1,4 @@ -package token +package secret import ( "encoding/json" @@ -22,7 +22,7 @@ func init() { if err != nil { return err } - networkID, err := cmd.Flags().GetString("network") + network, err := cmd.Flags().GetString("network") if err != nil { return err } @@ -30,18 +30,18 @@ func init() { if err != nil { return err } - token, err := auth.NewAuthenticator(secretKey).GenerateSecret(networkID, validDuration) + secret, err := auth.NewAuthenticator(secretKey).GenerateSecret(network, validDuration) if err != nil { return err } return json.NewEncoder(os.Stdout).Encode(peer.NetworkSecret{ - Secret: token, - Network: networkID, + Secret: secret, + Network: network, Expire: time.Now().Add(validDuration - 10*time.Second), }) }, } - Cmd.Flags().String("network", "", "network") + Cmd.Flags().String("network", "default", "network") Cmd.Flags().String("secret-key", "", "key to generate network secret") Cmd.Flags().Duration("duration", 365*24*time.Hour, "secret duration to expire") diff --git a/cmd/vpn/vpn.go b/cmd/pgcli/vpn/vpn.go similarity index 96% rename from cmd/vpn/vpn.go rename to cmd/pgcli/vpn/vpn.go index b51806d..cb07ea1 100644 --- a/cmd/vpn/vpn.go +++ b/cmd/pgcli/vpn/vpn.go @@ -25,7 +25,7 @@ import ( var Cmd = &cobra.Command{ Use: "vpn", - Short: "Run a vpn daemon powered by PeerGuard", + Short: "Run a vpn daemon which backend is PeerGuard p2p network", Args: cobra.NoArgs, RunE: run, } @@ -39,7 +39,7 @@ func init() { Cmd.Flags().String("key", "", "curve25519 private key in base64-url format (default generate a new one)") Cmd.Flags().String("secret-file", "", "p2p network secret file (default ~/.peerguard_network_secret.json)") - Cmd.Flags().StringSlice("peermap", []string{}, "peermap cluster") + Cmd.Flags().StringP("server", "s", "", "peermap server") Cmd.Flags().StringSlice("allowed-ip", []string{}, "declare IPs that can be routed/NATed by this machine (i.e. 192.168.0.0/24)") Cmd.Flags().StringSlice("peer", []string{}, "specify peers instead of auto-discovery (pg://?alias1=&alias2=)") @@ -48,7 +48,7 @@ func init() { Cmd.Flags().Duration("disco-challenges-initial-interval", 300*time.Millisecond, "ping challenges initial interval when disco") Cmd.Flags().Float64("disco-challenges-backoff-rate", 1.35, "ping challenges backoff rate when disco") - Cmd.MarkFlagRequired("peermap") + Cmd.MarkFlagRequired("server") Cmd.MarkFlagsOneRequired("ipv4", "ipv6") } @@ -105,10 +105,11 @@ func run(cmd *cobra.Command, args []string) (err error) { return } - cfg.Peermap, err = cmd.Flags().GetStringSlice("peermap") + server, err := cmd.Flags().GetString("server") if err != nil { return } + cfg.Peermap = peer.PeermapCluster{server} tunName, err := cmd.Flags().GetString("tun") if err != nil { diff --git a/cmd/serve/serve.go b/cmd/pgserve/main.go similarity index 55% rename from cmd/serve/serve.go rename to cmd/pgserve/main.go index 9d7b49f..3c683e6 100644 --- a/cmd/serve/serve.go +++ b/cmd/pgserve/main.go @@ -1,8 +1,9 @@ -package serve +package main import ( "context" "errors" + "fmt" "net/http" "os" "os/signal" @@ -12,18 +13,27 @@ import ( "github.com/spf13/cobra" ) -var Cmd = &cobra.Command{ - Use: "serve", - Short: "PeerGuard peermap daemon", - Args: cobra.NoArgs, - RunE: run, -} +var ( + Version = "unknown" + Commit = "unknown" +) -func init() { - Cmd.Flags().StringP("config", "c", "config.yaml", "config file") - Cmd.Flags().StringP("listen", "l", "", "listen http address (default 127.0.0.1:9987)") - Cmd.Flags().String("secret-key", "", "key to generate network secret (defaut generate a random one)") - Cmd.Flags().StringSlice("stun", []string{}, "stun server for peers NAT traversal (leave blank to disable NAT traversal)") +func main() { + serveCmd := &cobra.Command{ + Use: "pgserve", + Version: fmt.Sprintf("%s, commit %s", Version, Commit), + Short: "Run a peermap server daemon", + SilenceUsage: true, + Args: cobra.NoArgs, + RunE: run, + } + serveCmd.Flags().StringP("config", "c", "config.yaml", "config file") + serveCmd.Flags().StringP("listen", "l", "127.0.0.1:9987", "listen http address") + serveCmd.Flags().String("secret-key", "", "key to generate network secret (defaut generate a random one)") + serveCmd.Flags().StringSlice("stun", []string{}, "stun server for peers NAT traversal (leave blank to disable NAT traversal)") + serveCmd.Flags().IntP("verbose", "V", 0, "logger verbosity level") + + serveCmd.Execute() } func run(cmd *cobra.Command, args []string) error {