diff --git a/README.md b/README.md index ec84fecf..44d79bc0 100644 --- a/README.md +++ b/README.md @@ -2,27 +2,40 @@ Fully Decentralized. Immutable. Portable. Easy to use Statically compiled VPN +EdgeVPN uses libp2p to connect and create a blockchain between nodes. It keeps the routing table stored in the ledger, while connections are dynamically established via p2p. + ## Usage -Generate a config: +Generate a config, and send it over all the nodes you wish to connect: ```bash ./edgevpn -g > config.yaml ``` -Run it on multiple hosts: +Run edgevpn on multiple hosts: ```bash +# on Node A EDGEVPNCONFIG=config.yaml IFACE=edgevpn0 ADDRESS=10.1.0.11/24 ./edgevpn +# on Node B EDGEVPNCONFIG=config.yaml IFACE=edgevpn0 ADDRESS=10.1.0.12/24 ./edgevpn +# on Node C ... EDGEVPNCONFIG=config.yaml IFACE=edgevpn0 ADDRESS=10.1.0.13/24 ./edgevpn ... ``` -... and that's it! +... and that's it! the `ADDRESS` is a _virtual_ unique IP for each node, and it is actually the ip where the node will be reachable to from the vpn, while `IFACE` is the interface name. *Note*: It might take up time to build the connection between nodes. Wait at least 5 mins, it depends on the network behind the hosts. +## Architecture + +- p2p encryption between peers with libp2p +- randezvous points dynamically generated from OTP keys +- extra AES symmetric encryption on top. In case randezvous point is compromised +- blockchain is used as a sealed encrypted store for the routing table +- connections are created host to host + ## Is it for me? EdgeVPN makes VPN decentralization a first strong requirement. @@ -31,8 +44,8 @@ Its mainly use is for edge and low-end devices and especially for development. The decentralized approach has few cons: -- The underlaying network is chatty. It uses a Gossip protocol and p2p. Every message is broadcasted to all peers. -- Not suited for low latency. On my local tests on very slow connections, ping took ~200ms. +- The underlaying network is chatty. It uses a Gossip protocol for syncronizing the routing table and p2p. Every blockchain message is broadcasted to all peers, while the traffic is to the host only. +- Might be not suited for low latency workload. Keep that in mind before using it for your prod networks! @@ -82,12 +95,6 @@ e.Start() ``` -## Architecture - -- p2p encryption between peers with libp2p -- randezvous points dynamically generated from OTP keys -- extra AES symmetric encryption on top. In case randezvous point is compromised - ## Credits - The awesome [libp2p](https://github.com/libp2p) library diff --git a/go.mod b/go.mod index e732f145..dc4318fe 100644 --- a/go.mod +++ b/go.mod @@ -6,22 +6,22 @@ require ( github.com/ipfs/go-ipns v0.1.2 // indirect github.com/ipfs/go-log/v2 v2.3.0 github.com/kr/text v0.2.0 // indirect - github.com/libp2p/go-libp2p v0.15.0 + github.com/libp2p/go-libp2p v0.15.1 github.com/libp2p/go-libp2p-core v0.9.0 github.com/libp2p/go-libp2p-discovery v0.5.1 - github.com/libp2p/go-libp2p-kad-dht v0.11.1 + github.com/libp2p/go-libp2p-kad-dht v0.12.1 github.com/libp2p/go-libp2p-pubsub v0.5.4 - github.com/libp2p/go-libp2p-quic-transport v0.11.2 - github.com/libp2p/go-tcp-transport v0.2.8 + github.com/libp2p/go-libp2p-quic-transport v0.12.0 // indirect github.com/lthibault/jitterbug v2.0.0+incompatible github.com/multiformats/go-multiaddr v0.4.0 github.com/pkg/errors v0.9.1 github.com/songgao/packets v0.0.0-20160404182456-549a10cd4091 github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 - github.com/urfave/cli/v2 v2.3.0 github.com/vishvananda/netlink v1.1.0 github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119 + go.opencensus.io v0.23.0 // indirect go.uber.org/zap v1.19.0 + golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d gopkg.in/yaml.v2 v2.4.0 ) diff --git a/go.sum b/go.sum index adde0a85..01ca4b24 100644 --- a/go.sum +++ b/go.sum @@ -97,10 +97,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -126,9 +123,7 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -245,6 +240,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -252,7 +248,6 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= -github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -268,6 +263,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= @@ -299,8 +295,9 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -459,9 +456,9 @@ github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZk github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= -github.com/libp2p/go-libp2p v0.12.0/go.mod h1:FpHZrfC1q7nA8jitvdjKBDF31hguaC676g/nT9PgQM0= -github.com/libp2p/go-libp2p v0.15.0 h1:jbMbdmtizfpvl1+oQuGJzfGhttAtuxUCavF3enwFncg= -github.com/libp2p/go-libp2p v0.15.0/go.mod h1:8Ljmwon0cZZYKrOCjFeLwQEK8bqR42dOheUZ1kSKhP0= +github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= +github.com/libp2p/go-libp2p v0.15.1 h1:wSC//fziln3aMTwgF2vOl0v+hTSFfsdr686Fl0uD3ug= +github.com/libp2p/go-libp2p v0.15.1/go.mod h1:93vekOmNoLAcHXUYYEBot0Df/Z6tm46xu9NeCaiKdnM= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052 h1:BM7aaOF7RpmNn9+9g6uTjGJ0cTzWr5j9i9IKeun2M8U= github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= @@ -503,6 +500,7 @@ github.com/libp2p/go-libp2p-core v0.7.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJB github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= github.com/libp2p/go-libp2p-core v0.8.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= github.com/libp2p/go-libp2p-core v0.8.2/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.5/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= github.com/libp2p/go-libp2p-core v0.8.6/go.mod h1:dgHr0l0hIKfWpGpqAMbpo19pen9wJfdCGv51mTmdpmM= github.com/libp2p/go-libp2p-core v0.9.0 h1:t97Mv0LIBZlP2FXVRNKKVzHJCIjbIWGxYptGId4+htU= github.com/libp2p/go-libp2p-core v0.9.0/go.mod h1:ESsbz31oC3C1AvMJoGx26RTuCkNhmkSRCqZ0kQtJ2/8= @@ -512,8 +510,9 @@ github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQO github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= github.com/libp2p/go-libp2p-discovery v0.5.1 h1:CJylx+h2+4+s68GvrM4pGNyfNhOYviWBPtVv5PA7sfo= github.com/libp2p/go-libp2p-discovery v0.5.1/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= -github.com/libp2p/go-libp2p-kad-dht v0.11.1 h1:FsriVQhOUZpCotWIjyFSjEDNJmUzuMma/RyyTDZanwc= -github.com/libp2p/go-libp2p-kad-dht v0.11.1/go.mod h1:5ojtR2acDPqh/jXf5orWy8YGb8bHQDS+qeDcoscL/PI= +github.com/libp2p/go-libp2p-kad-dht v0.12.1 h1:6HsBhzxcD34rE7Ds2lK9q6llPE7/tdqV7JmJiukEcQ8= +github.com/libp2p/go-libp2p-kad-dht v0.12.1/go.mod h1:zdQYru1c7dnluMpZls4i9Fj2TwYXS7YyDkJ1Yahv0w0= +github.com/libp2p/go-libp2p-kbucket v0.3.1/go.mod h1:oyjT5O7tS9CQurok++ERgc46YLwEpuGoFq9ubvoUOio= github.com/libp2p/go-libp2p-kbucket v0.4.7 h1:spZAcgxifvFZHBD8tErvppbnNiKA5uokDu3CV7axu70= github.com/libp2p/go-libp2p-kbucket v0.4.7/go.mod h1:XyVo99AfQH0foSf176k4jY1xUJ2+jUJIZCSDm7r2YKk= github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= @@ -521,7 +520,7 @@ github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3 github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= -github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= +github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= github.com/libp2p/go-libp2p-mplex v0.4.1 h1:/pyhkP1nLwjG3OM+VuaNJkQT/Pqq73WzB3aDN3Fx1sc= github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= @@ -540,14 +539,16 @@ github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnq github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= github.com/libp2p/go-libp2p-peerstore v0.2.6/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= +github.com/libp2p/go-libp2p-peerstore v0.2.7/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= github.com/libp2p/go-libp2p-peerstore v0.2.8 h1:nJghUlUkFVvyk7ccsM67oFA6kqUkwyCM1G4WPVMCWYA= github.com/libp2p/go-libp2p-peerstore v0.2.8/go.mod h1:gGiPlXdz7mIHd2vfAsHzBNAMqSDkt2UBFwgcITgw1lA= github.com/libp2p/go-libp2p-pnet v0.2.0 h1:J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k= github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= github.com/libp2p/go-libp2p-pubsub v0.5.4 h1:rHl9/Xok4zX3zgi0pg0XnUj9Xj2OeXO8oTu85q2+YA8= github.com/libp2p/go-libp2p-pubsub v0.5.4/go.mod h1:gVOzwebXVdSMDQBTfH8ACO5EJ4SQrvsHqCmYsCZpD0E= -github.com/libp2p/go-libp2p-quic-transport v0.11.2 h1:p1YQDZRHH4Cv2LPtHubqlQ9ggz4CKng/REZuXZbZMhM= github.com/libp2p/go-libp2p-quic-transport v0.11.2/go.mod h1:wlanzKtIh6pHrq+0U3p3DY9PJfGqxMgPaGKaK5LifwQ= +github.com/libp2p/go-libp2p-quic-transport v0.12.0 h1:7IjDH4XNkmJbOMD+mxRloTe4LzMTq+vqvm2nYNL1N7M= +github.com/libp2p/go-libp2p-quic-transport v0.12.0/go.mod h1:EKHqxZbWE/FhDJZ6ebyZ/4v3X9zyuuuKIN0XR9vANT0= github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= github.com/libp2p/go-libp2p-record v0.1.3 h1:R27hoScIhQf/A8XJZ8lYpnqh9LatJ5YbHs28kCIfql0= github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= @@ -561,7 +562,7 @@ github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaT github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= -github.com/libp2p/go-libp2p-swarm v0.3.1/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.4.0/go.mod h1:XVFcO52VoLoo0eitSxNQWYq4D6sydGOweTOAjJNraCw= github.com/libp2p/go-libp2p-swarm v0.5.3 h1:hsYaD/y6+kZff1o1Mc56NcuwSg80lIphTS/zDk3mO4M= github.com/libp2p/go-libp2p-swarm v0.5.3/go.mod h1:NBn7eNW2lu568L7Ns9wdFrOhgRlkRnIDg0FLKbuu3i8= github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= @@ -580,9 +581,11 @@ github.com/libp2p/go-libp2p-tls v0.2.0/go.mod h1:twrp2Ci4lE2GYspA1AnlYm+boYjqVru github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= +github.com/libp2p/go-libp2p-transport-upgrader v0.4.0/go.mod h1:J4ko0ObtZSmgn5BX5AmegP+dK3CSnU2lMCKsSq/EY0s= github.com/libp2p/go-libp2p-transport-upgrader v0.4.3/go.mod h1:bpkldbOWXMrXhpZbSV1mQxTrefOg2Fi+k1ClDSA4ppw= github.com/libp2p/go-libp2p-transport-upgrader v0.4.6 h1:SHt3g0FslnqIkEWF25YOB8UCOCTpGAVvHRWQYJ+veiI= github.com/libp2p/go-libp2p-transport-upgrader v0.4.6/go.mod h1:JE0WQuQdy+uLZ5zOaI3Nw9dWGYJIA7mywEtP2lMvnyk= +github.com/libp2p/go-libp2p-xor v0.0.0-20200501025846-71e284145d58/go.mod h1:AYjOiqJIdcmI4SXE2ouKQuFrUbE5myv8txWaB2pl4TI= github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= @@ -590,6 +593,7 @@ github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhL github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.5.1/go.mod h1:dowuvDu8CRWmr0iqySMiSxK+W0iL5cMVO9S94Y6gkv4= github.com/libp2p/go-libp2p-yamux v0.5.4 h1:/UOPtT/6DHPtr3TtKXBHa6g0Le0szYuI33Xc/Xpd7fQ= github.com/libp2p/go-libp2p-yamux v0.5.4/go.mod h1:tfrXbyaTqqSU654GTvK3ocnSZL3BuHoeTSqhcel1wsE= github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= @@ -646,7 +650,7 @@ github.com/libp2p/go-tcp-transport v0.2.8 h1:aLjX+Nkz+kIz3uA56WtlGKRSAnKDvnqKmv1 github.com/libp2p/go-tcp-transport v0.2.8/go.mod h1:64rSfVidkYPLqbzpcN2IwHY4pmgirp67h++hZ/rcndQ= github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= -github.com/libp2p/go-ws-transport v0.3.1/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= +github.com/libp2p/go-ws-transport v0.4.0/go.mod h1:EcIEKqf/7GDjth6ksuS/6p7R49V4CBY6/E7R/iyhYUA= github.com/libp2p/go-ws-transport v0.5.0 h1:cO6x4P0v6PfxbKnxmf5cY2Ny4OPDGYkUqNvZzp/zdlo= github.com/libp2p/go-ws-transport v0.5.0/go.mod h1:I2juo1dNTbl8BKSBYo98XY85kU2xds1iamArLvl8kNg= github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= @@ -657,16 +661,18 @@ github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/h github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= github.com/libp2p/go-yamux v1.4.1 h1:P1Fe9vF4th5JOxxgQvfbOHkrGqIZniTLf+ddhZp8YTI= github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U= github.com/libp2p/go-yamux/v2 v2.2.0 h1:RwtpYZ2/wVviZ5+3pjC8qdQ4TKnrak0/E01N1UWoAFU= github.com/libp2p/go-yamux/v2 v2.2.0/go.mod h1:3So6P6TV6r75R9jiBpiIKgU/66lOarCZjqROGxzPpPQ= -github.com/libp2p/zeroconf/v2 v2.0.0 h1:qYAHAqUVh4hMSfu+iDTZNqH07wLGAvb1+DW4Tx/qUoQ= -github.com/libp2p/zeroconf/v2 v2.0.0/go.mod h1:J85R/d9joD8u8F9aHM8pBXygtG9W02enEwS+wWeL6yo= +github.com/libp2p/zeroconf/v2 v2.1.0 h1:9aZt2jwaBjkAJ/1cZnRTvzfN0eCDYaJWTjHST5tZIlk= +github.com/libp2p/zeroconf/v2 v2.1.0/go.mod h1:vtRu3WOBoLRiQ3BhDvIJwvvrRakbTevCVLSr9/Ljess= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lthibault/jitterbug v2.0.0+incompatible h1:qouq51IKzlMx25+15jbxhC/d79YyTj0q6XFoptNqaUw= github.com/lthibault/jitterbug v2.0.0+incompatible/go.mod h1:2l7akWd27PScEs6YkjyUVj/8hKgNhbbQ3KiJgJtlf6o= -github.com/lucas-clemente/quic-go v0.21.2 h1:8LqqL7nBQFDUINadW0fHV/xSaCQJgmJC0Gv+qUnjd78= github.com/lucas-clemente/quic-go v0.21.2/go.mod h1:vF5M1XqhBAHgbjKcJOXY3JZz3GP0T3FQhz/uyOUS38Q= +github.com/lucas-clemente/quic-go v0.23.0 h1:5vFnKtZ6nHDFsc/F3uuiF4T3y/AXaQdxjUqiVw26GZE= +github.com/lucas-clemente/quic-go v0.23.0/go.mod h1:paZuzjXCE5mj6sikVLMvqXk8lJV2AsqtJ6bDhjEfxx0= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -674,12 +680,12 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= -github.com/marten-seemann/qtls-go1-15 v0.1.5 h1:Ci4EIUN6Rlb+D6GmLdej/bCQ4nPYNtVXQB+xjiXE1nk= github.com/marten-seemann/qtls-go1-15 v0.1.5/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-16 v0.1.4 h1:xbHbOGGhrenVtII6Co8akhLEdrawwB2iHl5yhJRpnco= github.com/marten-seemann/qtls-go1-16 v0.1.4/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1 h1:/rpmWuGvceLwwWuaKPdjpR4JJEUH0tq64/I3hvzaNLM= github.com/marten-seemann/qtls-go1-17 v0.1.0-rc.1/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= +github.com/marten-seemann/qtls-go1-17 v0.1.0 h1:P9ggrs5xtwiqXv/FHNwntmuLMNq3KaSIG93AtAZ48xk= +github.com/marten-seemann/qtls-go1-17 v0.1.0/go.mod h1:fz4HIxByo+LlWcreM4CZOYNuz3taBQ8rN2X6FqvaWo8= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -896,9 +902,7 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= @@ -924,7 +928,6 @@ github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= @@ -975,16 +978,14 @@ github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cb github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a h1:G++j5e0OC488te356JvdhaM8YS6nMsjLAYF7JxCv07w= github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k= @@ -1017,8 +1018,9 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1152,6 +1154,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= @@ -1417,6 +1420,7 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= diff --git a/main.go b/main.go index 6e7c0cd8..a46c562b 100644 --- a/main.go +++ b/main.go @@ -41,11 +41,12 @@ func main() { edgevpn.Logger(l), edgevpn.LogLevel(log.LevelInfo), edgevpn.MaxMessageSize(2 << 20), // 2MB - edgevpn.WithMTU(1500), - edgevpn.WithInterfaceMTU(1300), + edgevpn.WithInterfaceMTU(1450), + edgevpn.WithPacketMTU(1420), edgevpn.WithInterfaceAddress(os.Getenv("ADDRESS")), edgevpn.WithInterfaceName(os.Getenv("IFACE")), - edgevpn.WithInterfaceType(water.TAP), + edgevpn.WithMaxBlockChainSize(1000), + edgevpn.WithInterfaceType(water.TUN), edgevpn.NetLinkBootstrap(true), } @@ -96,4 +97,7 @@ func main() { if err := e.Start(); err != nil { l.Sugar().Fatal(err.Error()) } + + for { + } } diff --git a/pkg/blockchain/block.go b/pkg/blockchain/block.go new file mode 100644 index 00000000..b6e16d17 --- /dev/null +++ b/pkg/blockchain/block.go @@ -0,0 +1,66 @@ +package blockchain + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "time" +) + +// Block represents each 'item' in the blockchain +type Block struct { + Index int + Timestamp string + AddressMap map[string]string + Hash string + PrevHash string +} + +// Blockchain is a series of validated Blocks +type Blockchain []Block + +func (b Blockchain) IsMoreRecent(bb Blockchain) bool { + return len(b) > len(bb) || len(b) == len(bb) && b[len(b)-1].Hash != bb[len(bb)-1].Hash +} + +// make sure block is valid by checking index, and comparing the hash of the previous block +func (newBlock Block) IsValid(oldBlock Block) bool { + if oldBlock.Index+1 != newBlock.Index { + return false + } + + if oldBlock.Hash != newBlock.PrevHash { + return false + } + + if newBlock.Checksum() != newBlock.Hash { + return false + } + + return true +} + +// Checksum does SHA256 hashing of the block +func (b Block) Checksum() string { + record := fmt.Sprint(b.Index, b.Timestamp, b.AddressMap, b.PrevHash) + h := sha256.New() + h.Write([]byte(record)) + hashed := h.Sum(nil) + return hex.EncodeToString(hashed) +} + +// create a new block using previous block's hash +func (oldBlock Block) NewBlock(s map[string]string) Block { + + var newBlock Block + + t := time.Now() + + newBlock.Index = oldBlock.Index + 1 + newBlock.Timestamp = t.String() + newBlock.AddressMap = s + newBlock.PrevHash = oldBlock.Hash + newBlock.Hash = newBlock.Checksum() + + return newBlock +} diff --git a/pkg/blockchain/ledger.go b/pkg/blockchain/ledger.go new file mode 100644 index 00000000..c305b670 --- /dev/null +++ b/pkg/blockchain/ledger.go @@ -0,0 +1,176 @@ +package blockchain + +import ( + "context" + "encoding/json" + "io" + "log" + "sync" + "time" + + "github.com/mudler/edgevpn/pkg/hub" +) + +type Ledger struct { + sync.Mutex + Blockchain Blockchain + + maxChainSize int + channel io.Writer +} + +// New returns a new ledger which writes to the writer +func New(w io.Writer, maxChainSize int) *Ledger { + c := &Ledger{channel: w, maxChainSize: maxChainSize} + c.newGenesis() + return c +} + +func (l *Ledger) newGenesis() { + t := time.Now() + genesisBlock := Block{} + genesisBlock = Block{0, t.String(), map[string]string{}, genesisBlock.Checksum(), ""} + l.Blockchain = append(l.Blockchain, genesisBlock) +} + +// Syncronizer starts a goroutine which +// writes the blockchain to the periodically +func (l *Ledger) Syncronizer(ctx context.Context, t time.Duration) { + go func() { + t := time.NewTicker(t) + defer t.Stop() + for { + select { + case <-t.C: + l.Lock() + bytes, err := json.Marshal(l.Blockchain) + if err != nil { + log.Println(err) + } + l.channel.Write(bytes) + + // Reset blockchain if we exceed chainsize + if l.maxChainSize != 0 && len(l.Blockchain) > l.maxChainSize { + l.Blockchain = []Block{} + } + l.Unlock() + case <-ctx.Done(): + return + } + } + }() +} + +// String returns the blockchain as string +func (l *Ledger) String() string { + bytes, _ := json.MarshalIndent(l.Blockchain, "", " ") + return string(bytes) +} + +// Update the blockchain from a message +func (l *Ledger) Update(h *hub.Message) (err error) { + chain := make(Blockchain, 0) + + err = json.Unmarshal([]byte(h.Message), &chain) + if err != nil { + return + } + + l.Lock() + if chain.IsMoreRecent(l.Blockchain) { + l.Blockchain = chain + } + l.Unlock() + + return +} + +// Persist an async data to the blockchain. +// Sends a broadcast at the specified interval +// by making sure the async retrieved value is written to the +// blockchain +func (l *Ledger) Persist(ctx context.Context, t time.Duration, key string, async func() string) { + go func() { + t := time.NewTicker(t) + defer t.Stop() + for { + select { + case <-t.C: + value := async() + // Retrieve current ID for ip in the blockchain + existingValue, found := l.GetKey(key) + // If mismatch, update the blockchain + if !found || existingValue != value { + updatedMap := map[string]string{} + updatedMap[key] = value + l.Add(updatedMap) + } + case <-ctx.Done(): + return + } + } + }() +} + +func (l *Ledger) lastBlock() Block { + return (l.Blockchain[len(l.Blockchain)-1]) +} + +// GetKey retrieve the current key from the blockchain +func (l *Ledger) GetKey(s string) (value string, exists bool) { + l.Lock() + defer l.Unlock() + if len(l.Blockchain) > 0 { + last := l.lastBlock() + value, exists = last.AddressMap[s] + if exists { + return + } + } + + return +} + +// ExistsValue returns true if there is one element with a matching value +func (l *Ledger) ExistsValue(v string) (exists bool) { + l.Lock() + defer l.Unlock() + if len(l.Blockchain) > 0 { + for _, bv := range l.lastBlock().AddressMap { + if bv == v { + exists = true + return + } + } + } + + return +} + +// Add data to the blockchain +func (l *Ledger) Add(s map[string]string) { + l.Lock() + current := l.lastBlock().AddressMap + for s, k := range s { + current[s] = k + } + l.Unlock() + l.writeData(current) +} + +func (l *Ledger) writeData(s map[string]string) { + newBlock := l.lastBlock().NewBlock(s) + + if newBlock.IsValid(l.lastBlock()) { + l.Lock() + l.Blockchain = append(l.Blockchain, newBlock) + l.Unlock() + } + + bytes, err := json.Marshal(l.Blockchain) + if err != nil { + log.Println(err) + } + + l.channel.Write(bytes) +} diff --git a/pkg/discovery/dht.go b/pkg/discovery/dht.go index 33ce8a25..185d6fcf 100644 --- a/pkg/discovery/dht.go +++ b/pkg/discovery/dht.go @@ -96,7 +96,6 @@ func (d *DHT) Run(c *zap.Logger, ctx context.Context, host host.Host) error { } go func() { - connect() t := jitterbug.New( @@ -149,29 +148,31 @@ func (d *DHT) announceAndConnect(ctx context.Context, kademliaDHT *dht.IpfsDHT, if err != nil { return err } - var wg sync.WaitGroup + // var wg sync.WaitGroup for p := range peerChan { // Don't dial ourselves or peers without address if p.ID == host.ID() || len(p.Addrs) == 0 { continue } - wg.Add(1) - go func(a peer.AddrInfo) { - defer wg.Done() - - if host.Network().Connectedness(p.ID) != network.Connected { - d.console.Sugar().Info("Found peer:", a) - if err := host.Connect(ctx, a); err != nil { - d.console.Sugar().Info("Failed connecting to", a) - } else { - d.console.Sugar().Info("Connected to:", a) - } + // wg.Add(1) + // go func(a peer.AddrInfo) { + // defer wg.Done() + + if host.Network().Connectedness(p.ID) != network.Connected { + d.console.Sugar().Info("Found peer:", p) + if err := host.Connect(ctx, p); err != nil { + d.console.Sugar().Info("Failed connecting to", p) + } else { + d.console.Sugar().Info("Connected to:", p) } - }(p) + } else { + d.console.Sugar().Info("Known peer (already connected):", p) + } + //}(p) } - wg.Wait() + // wg.Wait() return nil } diff --git a/pkg/edgevpn/config.go b/pkg/edgevpn/config.go index ee760f1a..c7cb8d8d 100644 --- a/pkg/edgevpn/config.go +++ b/pkg/edgevpn/config.go @@ -28,18 +28,20 @@ type Config struct { Handlers []Handler MaxMessageSize int - MTU int SealKeyInterval int Interface *water.Interface InterfaceName string InterfaceAddress string InterfaceMTU int + MTU int DeviceType water.DeviceType ServiceDiscovery []ServiceDiscovery Logger *zap.Logger SealKeyLength int + MaxBlockChainLength int + NetLinkBootstrap bool // Handle is a handle consumed by HumanInterfaces to handle received messages diff --git a/pkg/edgevpn/connection.go b/pkg/edgevpn/connection.go index 8acebed4..153d522d 100644 --- a/pkg/edgevpn/connection.go +++ b/pkg/edgevpn/connection.go @@ -16,6 +16,8 @@ import ( "github.com/xlzd/gotp" ) +const Protocol = "/edgevpn/0.1" + var defaultLibp2pOptions = []libp2p.Option{ libp2p.EnableAutoRelay(), libp2p.EnableNATService(), @@ -27,7 +29,6 @@ func (e *EdgeVPN) Host() host.Host { } func (e *EdgeVPN) genHost(ctx context.Context) (host.Host, error) { - var r io.Reader if e.seed == 0 { r = rand.Reader @@ -85,8 +86,7 @@ func (e *EdgeVPN) genHost(ctx context.Context) (host.Host, error) { } func (e *EdgeVPN) sealkey() string { - totp := gotp.NewTOTP(e.config.ExchangeKey, 6, e.config.SealKeyInterval, nil) - return totp.Now() + return gotp.NewTOTP(e.config.ExchangeKey, 6, e.config.SealKeyInterval, nil).Now() } func (e *EdgeVPN) handleEvents(ctx context.Context) { @@ -112,7 +112,9 @@ func (e *EdgeVPN) handleEvents(ctx context.Context) { func (e *EdgeVPN) handleReceivedMessage(m *hub.Message) { for _, h := range e.config.Handlers { - h(m) + if err := h(m); err != nil { + e.config.Logger.Sugar().Warnf("handler error: %s", err) + } } } diff --git a/pkg/edgevpn/edgevpn.go b/pkg/edgevpn/edgevpn.go index aa17a584..f061687d 100644 --- a/pkg/edgevpn/edgevpn.go +++ b/pkg/edgevpn/edgevpn.go @@ -2,14 +2,20 @@ package edgevpn import ( "context" - "fmt" + "io" + "net" + "time" "github.com/libp2p/go-libp2p-core/host" + "github.com/libp2p/go-libp2p-core/network" + "github.com/libp2p/go-libp2p-core/peer" + "github.com/libp2p/go-libp2p-core/protocol" pubsub "github.com/libp2p/go-libp2p-pubsub" + "github.com/mudler/edgevpn/pkg/blockchain" hub "github.com/mudler/edgevpn/pkg/hub" "github.com/songgao/packets/ethernet" "github.com/songgao/water" - "go.uber.org/zap" + "golang.org/x/net/ipv4" ) type EdgeVPN struct { @@ -18,7 +24,6 @@ type EdgeVPN struct { doneCh chan struct{} inputCh chan *hub.Message seed int64 - nick string host host.Host } @@ -34,6 +39,24 @@ func New(p ...Option) *EdgeVPN { } } +// keeps syncronized the blockchain with the node IP +func (e *EdgeVPN) adverizer(ip net.IP, ledger *blockchain.Ledger) { + for { + time.Sleep(5 * time.Second) + + nodeID := e.host.ID().String() + // Retrieve current ID for ip in the blockchain + existingPeerID, found := ledger.GetKey(ip.String()) + // If mismatch, update the blockchain + if !found || existingPeerID != nodeID { + updatedMap := map[string]string{} + updatedMap[ip.String()] = nodeID + ledger.Add(updatedMap) + } + } +} + +// Start the vpn. Returns an error in case of failure func (e *EdgeVPN) Start() error { ifce, err := e.createInterface() if err != nil { @@ -41,22 +64,39 @@ func (e *EdgeVPN) Start() error { } defer ifce.Close() - // Set the handler when we receive packages - e.config.Handlers = append(e.config.Handlers, IfaceWriter(ifce)) + mw, err := e.MessageWriter() + if err != nil { + return err + } + + ledger := blockchain.New(mw, e.config.MaxBlockChainLength) + + // Set the handler when we receive messages + // The ledger needs to read them and update the internal blockchain + e.config.Handlers = append(e.config.Handlers, ledger.Update) e.config.Logger.Sugar().Info("starting edgevpn background daemon") // Startup libp2p network - err = e.network() + err = e.network(ledger, ifce) if err != nil { return err } - // Write packets from interface - return e.writePackets(ifce) -} + // Avoid to loopback traffic by trying to connect to nodes in via VPN + ip, _, err := net.ParseCIDR(e.config.InterfaceAddress) + if err != nil { + return err + } -func (e *EdgeVPN) writePackets(ifce *water.Interface) error { + // Updates the blockchain + ledger.Syncronizer(context.Background(), 5*time.Second) + ledger.Persist( + context.Background(), + 5*time.Second, + ip.String(), + func() string { return e.host.ID().String() }, + ) if e.config.NetLinkBootstrap { if err := e.prepareInterface(); err != nil { @@ -64,30 +104,17 @@ func (e *EdgeVPN) writePackets(ifce *water.Interface) error { } } - mw, err := e.MessageWriter() - if err != nil { - return err - } - var frame ethernet.Frame + // read packets from the interface + return e.readPackets(ledger, ifce) +} - for { - frame.Resize(e.config.MTU) - n, err := ifce.Read([]byte(frame)) - if err != nil { - return err - } - frame = frame[:n] - mw.Write(frame) - e.config.Logger.Debug("packet", - zap.String("dst", frame.Destination().String()), - zap.String("Src", frame.Source().String()), - zap.String("Ethertype", fmt.Sprint(frame.Ethertype())), - zap.String("Payload", fmt.Sprint(frame.Payload())), - zap.String("dst", frame.Destination().String()), - ) - } +// end signals the event loop to exit gracefully +func (e *EdgeVPN) Stop() { + e.doneCh <- struct{}{} } +// MessageWriter returns a new MessageWriter bound to the edgevpn instance +// with the given options func (e *EdgeVPN) MessageWriter(opts ...hub.MessageOption) (*MessageWriter, error) { mess := &hub.Message{} mess.Apply(opts...) @@ -99,26 +126,79 @@ func (e *EdgeVPN) MessageWriter(opts ...hub.MessageOption) (*MessageWriter, erro }, nil } -func (e *EdgeVPN) network() error { +func (e *EdgeVPN) streamHandler(ledger *blockchain.Ledger, ifce *water.Interface) func(stream network.Stream) { + return func(stream network.Stream) { + if !ledger.ExistsValue(stream.Conn().RemotePeer().String()) { + stream.Reset() + return + } + io.Copy(ifce.ReadWriteCloser, stream) + stream.Close() + } +} + +// redirects packets from the interface to the node using the routing table in the blockchain +func (e *EdgeVPN) readPackets(ledger *blockchain.Ledger, ifce *water.Interface) error { + ctx := context.Background() + for { + var frame ethernet.Frame + frame.Resize(e.config.MTU) + n, err := ifce.Read([]byte(frame)) + if err != nil { + e.config.Logger.Sugar().Debug("could not read from interface") + return err + } + frame = frame[:n] + + header, err := ipv4.ParseHeader(frame) + if err != nil { + e.config.Logger.Sugar().Infof("could not parase ipv4 header from frame") + continue + } + + dst := header.Dst.String() + + // Query the routing table + value, found := ledger.GetKey(dst) + if !found { + e.config.Logger.Sugar().Infof("'%s' not found in the routing table", dst) + continue + } + // Decode the Peer + d, err := peer.Decode(value) + if err != nil { + e.config.Logger.Sugar().Infof("could not decode peer '%s'", value) + continue + } + + // Open a stream + stream, err := e.host.NewStream(ctx, d, Protocol) + if err != nil { + e.config.Logger.Sugar().Infof("could not open stream '%s'", err.Error()) + continue + } + stream.Write(frame) + stream.Close() + } +} + +func (e *EdgeVPN) network(ledger *blockchain.Ledger, ifce *water.Interface) error { ctx := context.Background() e.config.Logger.Sugar().Info("generating host data") host, err := e.genHost(ctx) if err != nil { e.config.Logger.Sugar().Error(err.Error()) - return err } e.host = host + host.SetStreamHandler(protocol.ID(Protocol), e.streamHandler(ledger, ifce)) + e.config.Logger.Sugar().Info("Host created. We are:", host.ID()) e.config.Logger.Sugar().Info(host.Addrs()) - // Set a function as stream handler. This function is called when a peer - // initiates a connection and starts a stream with this peer. - //host.SetStreamHandler(protocol.ID(e.config.ProtocolID), w.handleStream) - // create a new PubSub service using the GossipSub router ps, err := pubsub.NewGossipSub(ctx, host, pubsub.WithMaxMessageSize(e.config.MaxMessageSize)) if err != nil { @@ -145,8 +225,3 @@ func (e *EdgeVPN) network() error { return nil } - -// end signals the event loop to exit gracefully -func (e *EdgeVPN) Stop() { - e.doneCh <- struct{}{} -} diff --git a/pkg/edgevpn/interface_windows.go b/pkg/edgevpn/interface_windows.go deleted file mode 100644 index 77569219..00000000 --- a/pkg/edgevpn/interface_windows.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build windows - -package edgevpn - -import "github.com/songgao/water" - -func (e *EdgeVPN) prepareInterface() error { - - return nil -} - -func (e *EdgeVPN) createInterface() (*water.Interface, error) { - config := water.Config{ - DeviceType: e.config.DeviceType, - } - - return water.New(config) -} diff --git a/pkg/edgevpn/message.go b/pkg/edgevpn/message.go index 8c272a6d..d4ebae8e 100644 --- a/pkg/edgevpn/message.go +++ b/pkg/edgevpn/message.go @@ -20,6 +20,10 @@ func (mw *MessageWriter) Write(p []byte) (n int, err error) { return mw.Send(mw.mess.WithMessage(string(p))) } +func (mw *MessageWriter) WriteString(p string) (n int, err error) { + return mw.Send(mw.mess.WithMessage(p)) +} + func (mw *MessageWriter) Send(copy *hub.Message) (n int, err error) { mw.input <- copy return len(copy.Message), nil diff --git a/pkg/edgevpn/options.go b/pkg/edgevpn/options.go index 59a614b2..5df0daba 100644 --- a/pkg/edgevpn/options.go +++ b/pkg/edgevpn/options.go @@ -6,7 +6,6 @@ import ( "github.com/ipfs/go-log/v2" "github.com/libp2p/go-libp2p" discovery "github.com/mudler/edgevpn/pkg/discovery" - "github.com/mudler/edgevpn/pkg/hub" "github.com/mudler/edgevpn/pkg/utils" "github.com/pkg/errors" "github.com/songgao/water" @@ -16,13 +15,6 @@ import ( "gopkg.in/yaml.v2" ) -func IfaceWriter(i *water.Interface) Handler { - return Handler(func(m *hub.Message) error { - i.Write([]byte(m.Message)) - return nil - }) -} - // WithLibp2pOptions Overrides defaults options func WithLibp2pOptions(i ...libp2p.Option) func(cfg *Config) error { return func(cfg *Config) error { @@ -59,6 +51,20 @@ func WithInterfaceMTU(i int) func(cfg *Config) error { } } +func WithMaxBlockChainSize(i int) func(cfg *Config) error { + return func(cfg *Config) error { + cfg.MaxBlockChainLength = i + return nil + } +} + +func WithPacketMTU(i int) func(cfg *Config) error { + return func(cfg *Config) error { + cfg.MTU = i + return nil + } +} + func WithInterfaceType(d water.DeviceType) func(cfg *Config) error { return func(cfg *Config) error { cfg.DeviceType = d @@ -83,9 +89,7 @@ func Logger(l *zap.Logger) func(cfg *Config) error { // Handlers adds a handler to the list that is called on each received message func Handlers(h ...Handler) func(cfg *Config) error { return func(cfg *Config) error { - for _, cc := range h { - cfg.Handlers = append(cfg.Handlers, cc) - } + cfg.Handlers = append(cfg.Handlers, h...) return nil } } @@ -93,9 +97,7 @@ func Handlers(h ...Handler) func(cfg *Config) error { // DiscoveryService Adds the service given as argument to the discovery services func DiscoveryService(s ...ServiceDiscovery) func(cfg *Config) error { return func(cfg *Config) error { - for _, cc := range s { - cfg.ServiceDiscovery = append(cfg.ServiceDiscovery, cc) - } + cfg.ServiceDiscovery = append(cfg.ServiceDiscovery, s...) return nil } } @@ -149,13 +151,6 @@ func SealKeyInterval(i int) func(cfg *Config) error { } } -func WithMTU(i int) func(cfg *Config) error { - return func(cfg *Config) error { - cfg.MTU = i - return nil - } -} - func SealKeyLength(i int) func(cfg *Config) error { return func(cfg *Config) error { cfg.SealKeyLength = i @@ -205,7 +200,7 @@ type YAMLConnectionConfig struct { MDNS string `yaml:"mdns"` } -func (y YAMLConnectionConfig) Fill(cfg *Config) { +func (y YAMLConnectionConfig) copy(cfg *Config) { d := &discovery.DHT{ RefreshDiscoveryTime: 60, OTPInterval: y.OTP.DHT.Interval, @@ -249,7 +244,7 @@ func FromYaml(path string) func(cfg *Config) error { if err := yaml.Unmarshal(data, &t); err != nil { return errors.Wrap(err, "parsing yaml") } - t.Fill(cfg) + t.copy(cfg) return nil } }