diff --git a/go.mod b/go.mod index 1f1817136c4..8de56be88b9 100644 --- a/go.mod +++ b/go.mod @@ -41,15 +41,16 @@ require ( github.com/streamrail/concurrent-map v0.0.0-20160823150647-8bf1e9bacbf6 // indirect github.com/stretchr/testify v1.6.1 github.com/ti-mo/conntrack v0.3.0 - github.com/vishvananda/netlink v1.1.0 + github.com/vishvananda/netlink v1.1.1-0.20210510164352-d17758a128bf github.com/vmware/go-ipfix v0.5.2 - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 + golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 golang.org/x/mod v0.4.0 - golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 + golang.org/x/net v0.0.0-20210504132125-bbd867fde50d golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 - golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 + golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba + golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5 google.golang.org/grpc v1.27.1 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 77589f02762..bc592d952b2 100644 --- a/go.sum +++ b/go.sum @@ -301,6 +301,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/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.2/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= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -369,9 +370,16 @@ github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6t github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 h1:uhL5Gw7BINiiPAo24A2sxkcDI0Jt/sqp1v5xQCniEFA= +github.com/josharian/native v0.0.0-20200817173448-b6b71def0850/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= -github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4 h1:nwOc1YaOrYJ37sEBrtWZrdqzK22hiJs3GpDmP3sR2Yw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= +github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= +github.com/jsimonetti/rtnetlink v0.0.0-20201216134343-bde56ed16391/go.mod h1:cR77jAZG3Y3bsb8hF6fHJbFoyFukLFOkQ98S0pQz3xw= +github.com/jsimonetti/rtnetlink v0.0.0-20201220180245-69540ac93943/go.mod h1:z4c53zj6Eex712ROyh8WI0ihysb5j2ROyV42iNogmAs= +github.com/jsimonetti/rtnetlink v0.0.0-20210122163228-8d122574c736/go.mod h1:ZXpIyOK59ZnN7J0BV99cZUPmsqDRZ3eq5X+st7u/oSA= +github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b h1:c3NTyLNozICy8B4mlMXemD3z/gXgQzVXZS/HqT+i3do= +github.com/jsimonetti/rtnetlink v0.0.0-20210212075122-66c871082f2b/go.mod h1:8w9Rh8m+aHZIG69YPGGem1i5VzoyRC8nw2kA8B+ik5U= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= @@ -427,11 +435,23 @@ github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43 h1:WgyLFv10Ov49JAQI/ZLUkCZ7VJS3r74hwFIGXJsgZlY= +github.com/mdlayher/ethtool v0.0.0-20210210192532-2b88debcdd43/go.mod h1:+t7E0lkKfbBsebllff1xdTmyJt8lH37niI6kwFk9OTo= +github.com/mdlayher/genetlink v1.0.0 h1:OoHN1OdyEIkScEmRgxLEe2M9U8ClMytqA5niynLtfj0= +github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= -github.com/mdlayher/netlink v1.1.0 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg= github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= +github.com/mdlayher/netlink v1.2.0/go.mod h1:kwVW1io0AZy9A1E2YYgaD4Cj+C+GPkU6klXCMzIJ9p8= +github.com/mdlayher/netlink v1.2.1/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= +github.com/mdlayher/netlink v1.2.2-0.20210123213345-5cc92139ae3e/go.mod h1:bacnNlfhqHqqLo4WsYeXSqfyXkInQ9JneWI68v1KwSU= +github.com/mdlayher/netlink v1.3.0/go.mod h1:xK/BssKuwcRXHrtN04UBkwQ6dY9VviGGuriDdoPSWys= +github.com/mdlayher/netlink v1.4.0 h1:n3ARR+Fm0dDv37dj5wSWZXDKcy+U0zwcXS3zKMnSiT0= +github.com/mdlayher/netlink v1.4.0/go.mod h1:dRJi5IABcZpBD2A3D0Mv/AiX8I9uDEu5oGkAVrekmf8= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721 h1:RlZweED6sbSArvlE924+mUcZuXKLBHA35U7LN621Bws= +github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -594,11 +614,13 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20210510164352-d17758a128bf h1:JMdq3oWN6LQKfRpwVfjwuaZcPN4vGdVBzvOU2mzUXd8= +github.com/vishvananda/netlink v1.1.1-0.20210510164352-d17758a128bf/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -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/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae h1:4hwBBUfQCFe3Cym0ZtKyq7L16eZUtYKs+BaHDN6mAns= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/go-ipfix v0.5.2 h1:5VIW+HoJoq2i/mhN8ErNSYXNpjbtALImLIH72xh2Afc= github.com/vmware/go-ipfix v0.5.2/go.mod h1:rMDcGc5pEmG+wT2grK5ZgvsF1EOdxqHDnNkB/kFJT78= github.com/wenyingd/ofnet v0.0.0-20210318032909-171b6795a2da h1:ragN21nQa4zKuCwR2UEbTXEAh3L2YN/Id5SCVkjjwdY= @@ -647,8 +669,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI= +golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -718,10 +741,16 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 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-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 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-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM= +golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210504132125-bbd867fde50d h1:nTDGCTeAu2LhcsHTRzjyIUbZHCJ4QePArsm27Hka0UM= +golang.org/x/net v0.0.0-20210504132125-bbd867fde50d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -774,18 +803,30 @@ golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 h1:8qxJSnu+7dRq6upnbntrmriWByIakBuct5OM/MdQC1M= +golang.org/x/sys v0.0.0-20210123111255-9b0068b26619/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210216163648-f7da38b97c65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 h1:cdsMqa2nXzqlgs183pHxtvoVwU7CyzaCTAUOg94af4c= +golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -795,8 +836,9 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -850,6 +892,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.zx2c4.com/wireguard v0.0.0-20210427022245-097af6e1351b h1:XDLXhn7ryprJVo+Lpkiib6CIuXE2031GDwtfEm7vLjI= +golang.zx2c4.com/wireguard v0.0.0-20210427022245-097af6e1351b/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg= +golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5 h1:LpEwXnbN4q2EIPkqbG9KHBUrducJYDOOdL+eMcJAlFo= +golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5/go.mod h1:+1XihzyZUBJcSc5WO9SwNA7v26puQwOEDwanaxfNXPQ= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= diff --git a/pkg/agent/wireguard/client.go b/pkg/agent/wireguard/client.go new file mode 100644 index 00000000000..9fb68760dc3 --- /dev/null +++ b/pkg/agent/wireguard/client.go @@ -0,0 +1,323 @@ +package wireguard + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net" + "strconv" + "sync" + + "github.com/vishvananda/netlink" + "golang.org/x/sys/unix" + "golang.zx2c4.com/wireguard/wgctrl" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apitypes "k8s.io/apimachinery/pkg/types" + clientset "k8s.io/client-go/kubernetes" + "k8s.io/client-go/util/retry" + "k8s.io/klog/v2" + + "antrea.io/antrea/pkg/agent/types" + "antrea.io/antrea/pkg/agent/util/sysctl" +) + +const ( + ifname = "antrea-wg" + listenPort = 51850 + routeMask = 0x100 + routeMark = 0x100 + routeRulePriority = 10 + routeTable = 10 +) + +type Interface interface { + Init() error + UpdatePeer(nodeName, publicKeyString string, nodeIPv4, nodeIPv6 net.IP) error + RemoveStalePeers(currentPeerPublickeys []string) error + DeletePeer(nodeName string) error +} + +var _ Interface = (*client)(nil) + +// wireguardClient is an interface to mock wgctrl.Client +type wireguardClient interface { + io.Closer + Devices() ([]*wgtypes.Device, error) + Device(name string) (*wgtypes.Device, error) + ConfigureDevice(name string, config wgtypes.Config) error +} + +type client struct { + sync.Mutex + wgClient wireguardClient + nodeName string + k8sclient clientset.Interface + mtu int + listenPort int + privateKey wgtypes.Key + peerByNodeName map[string]wgtypes.PeerConfig + enabledIPv4, enabledIPv6 bool + nodeIPv4, nodeIPv6 net.IP +} + +func New(nodeName string, k8sclient clientset.Interface, mtu int, nodeIPv4, nodeIPv6 net.IP, enabledIPv4, enabledIPv6 bool, port int) (Interface, error) { + if port == 0 { + port = listenPort + } + wgClient, err := wgctrl.New() + if err != nil { + return nil, err + } + return &client{ + wgClient: wgClient, + nodeName: nodeName, + k8sclient: k8sclient, + mtu: mtu, + listenPort: port, + nodeIPv4: nodeIPv4, + nodeIPv6: nodeIPv6, + enabledIPv4: enabledIPv4, + enabledIPv6: enabledIPv6, + peerByNodeName: make(map[string]wgtypes.PeerConfig), + }, nil +} + +func (client *client) Init() error { + link := &netlink.Wireguard{LinkAttrs: netlink.LinkAttrs{Name: ifname}} + err := netlink.LinkAdd(link) + // ignore existing link as it might be managed by userspace process + if err != nil && !errors.Is(err, unix.EEXIST) { + if errors.Is(err, unix.EOPNOTSUPP) { + return fmt.Errorf("wireguard not supported by the Linux kernel (netlink: %w)", err) + } + return err + + } + if err := netlink.LinkSetUp(link); err != nil { + return err + } + if err := netlink.LinkSetMTU(link, client.mtu); err != nil { + return err + } + if client.enabledIPv4 { + if sysctl.EnsureSysctlNetValue("ipv4/conf/all/rp_filter", 0) != nil { + return fmt.Errorf("setting net.ipv4.conf.all.rp_filter failed: %w", err) + } + if sysctl.EnsureSysctlNetValue(fmt.Sprintf("ipv4/conf/%s/rp_filter", ifname), 0) != nil { + return fmt.Errorf("setting net.ipv4.conf.%s.rp_filter failed: %w", ifname, err) + } + if err := client.ensureRouting(netlink.FAMILY_V4); err != nil { + return err + } + } + if client.enabledIPv6 { + if err := client.ensureRouting(netlink.FAMILY_V6); err != nil { + return err + } + } + + wgdev, err := client.wgClient.Device(ifname) + if err != nil { + return nil + } + client.privateKey = wgdev.PrivateKey + var privateKeyExist bool + for _, b := range client.privateKey { + if b != 0 { + privateKeyExist = true + break + } + } + if !privateKeyExist { + newPkey, err := wgtypes.GeneratePrivateKey() + if err != nil { + return err + } + client.privateKey = newPkey + } + + cfg := wgtypes.Config{ + PrivateKey: &client.privateKey, + ListenPort: &client.listenPort, + ReplacePeers: false, + } + + klog.Infof("Updating node public key annotation") + patch, _ := json.Marshal(map[string]interface{}{ + "metadata": map[string]interface{}{ + "annotations": map[string]string{ + types.NodeWireGuardPublicKey: client.privateKey.PublicKey().String(), + }, + }, + }) + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + _, err := client.k8sclient.CoreV1().Nodes().Patch(context.TODO(), client.nodeName, apitypes.MergePatchType, patch, metav1.PatchOptions{}) + return err + }); err != nil { + return err + } + + return client.wgClient.ConfigureDevice(ifname, cfg) +} + +func (client *client) RemoveStalePeers(existingPeerPublickeys []string) error { + wgdev, err := client.wgClient.Device(ifname) + if err != nil { + return err + } + restoredPeerPublicKeys := make(map[wgtypes.Key]struct{}) + for _, peer := range wgdev.Peers { + restoredPeerPublicKeys[peer.PublicKey] = struct{}{} + } + for _, e := range existingPeerPublickeys { + pubKey, err := wgtypes.ParseKey(e) + if err != nil { + klog.Warning("Parse wireguard public key error %w", err) + continue + } + delete(restoredPeerPublicKeys, pubKey) + } + for k := range restoredPeerPublicKeys { + if err := client.deletePeerByPublicKey(k); err != nil { + klog.Warning("delete wireguard peer error", err) + } + } + return nil +} + +func (client *client) UpdatePeer(nodeName, publicKeyString string, nodeIPv4, nodeIPv6 net.IP) error { + client.Lock() + defer client.Unlock() + pubKey, err := wgtypes.ParseKey(publicKeyString) + if err != nil { + return err + } + var endpoint string + // We can only set one endpoint for each peer. Shoud we prioritize using IPv6? + if client.enabledIPv4 && nodeIPv4 != nil { + endpoint = net.JoinHostPort(nodeIPv4.String(), strconv.Itoa(listenPort)) + } else if client.enabledIPv6 && nodeIPv6 != nil { + endpoint = net.JoinHostPort(nodeIPv6.String(), strconv.Itoa(listenPort)) + } else { + return fmt.Errorf("node IP missing: %s", nodeName) + } + if peer, exist := client.peerByNodeName[nodeName]; exist { + if peer.PublicKey.String() != publicKeyString { + klog.Infof("peer %q public key changed to %s", nodeName, publicKeyString) + // delete old peer + if err := client.deletePeerByPublicKey(peer.PublicKey); err != nil { + return err + } + } + } + var allowedIPs []net.IPNet + if nodeIPv4 != nil { + allowedIPs = append(allowedIPs, net.IPNet{ + IP: nodeIPv4, + Mask: net.CIDRMask(net.IPv4len*8, net.IPv4len*8), + }) + } + if nodeIPv6 != nil { + allowedIPs = append(allowedIPs, net.IPNet{ + IP: nodeIPv6, + Mask: net.CIDRMask(net.IPv6len*8, net.IPv6len*8), + }) + } + endpointUDP, err := net.ResolveUDPAddr("udp", endpoint) + if err != nil { + return err + } + peerConfig := wgtypes.PeerConfig{ + PublicKey: pubKey, + Endpoint: endpointUDP, + AllowedIPs: allowedIPs, + ReplaceAllowedIPs: true, + } + client.peerByNodeName[nodeName] = peerConfig + cfg := wgtypes.Config{ + ReplacePeers: false, + Peers: []wgtypes.PeerConfig{peerConfig}, + } + return client.wgClient.ConfigureDevice(ifname, cfg) +} + +func (client *client) deletePeerByPublicKey(pubKey wgtypes.Key) error { + cfg := wgtypes.Config{Peers: []wgtypes.PeerConfig{ + {PublicKey: pubKey, Remove: true}, + }} + return client.wgClient.ConfigureDevice(ifname, cfg) +} + +func (client *client) DeletePeer(nodeName string) error { + peer, exist := client.peerByNodeName[nodeName] + if !exist { + return nil + } + if err := client.deletePeerByPublicKey(peer.PublicKey); err != nil { + return err + } + delete(client.peerByNodeName, nodeName) + return nil +} + +// ensureRouting set route rule, route table and default route for marked traffic +func (client *client) ensureRouting(ipFamily int) error { + rule := netlink.NewRule() + rule.Mark = routeMark + rule.Mask = routeMask + rule.Priority = routeRulePriority + rule.Table = routeTable + rule.Family = ipFamily + exist, err := lookupRule(rule, ipFamily) + if err != nil { + return err + } + if !exist { + if err := netlink.RuleAdd(rule); err != nil { + klog.Errorf("failed to add IP rule for WireGuard: %v", err) + return err + } + } + link, err := netlink.LinkByName(ifname) + if err != nil { + return err + } + rt := netlink.Route{ + LinkIndex: link.Attrs().Index, + Table: routeTable, + Scope: netlink.SCOPE_LINK, + } + if ipFamily == netlink.FAMILY_V4 { + rt.Dst = &net.IPNet{ + IP: net.IPv4zero, + Mask: net.CIDRMask(0, net.IPv4len), + } + rt.Src = client.nodeIPv4 + } else if ipFamily == netlink.FAMILY_V6 { + rt.Dst = &net.IPNet{ + IP: net.IPv6zero, + Mask: net.CIDRMask(0, net.IPv6len), + } + rt.Src = client.nodeIPv6 + } + return netlink.RouteReplace(&rt) +} + +// lookupRule checks whether existing rule matches. We only care the +func lookupRule(rule *netlink.Rule, family int) (bool, error) { + rules, err := netlink.RuleList(family) + if err != nil { + return false, err + } + for _, r := range rules { + if rule.Priority != r.Priority || r.Mask != rule.Mask || + r.Mark != rule.Mark || rule.Table != r.Table { + continue + } + return true, nil + } + return false, nil +} diff --git a/pkg/agent/wireguard/client_test.go b/pkg/agent/wireguard/client_test.go new file mode 100644 index 00000000000..762dde2215f --- /dev/null +++ b/pkg/agent/wireguard/client_test.go @@ -0,0 +1,244 @@ +package wireguard + +import ( + "net" + "testing" + + "github.com/stretchr/testify/assert" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" +) + +type fakeWireGuardClient struct { + peers map[wgtypes.Key]wgtypes.Peer +} + +func (f *fakeWireGuardClient) Close() error { + return nil +} + +func (f *fakeWireGuardClient) Devices() ([]*wgtypes.Device, error) { + return nil, nil +} + +func (f *fakeWireGuardClient) Device(name string) (*wgtypes.Device, error) { + var res []wgtypes.Peer + for _, p := range f.peers { + res = append(res, p) + } + return &wgtypes.Device{ + Peers: res, + }, nil +} + +func (f *fakeWireGuardClient) ConfigureDevice(name string, cfg wgtypes.Config) error { + for _, c := range cfg.Peers { + if c.Remove { + delete(f.peers, c.PublicKey) + } else { + peer := wgtypes.Peer{ + PublicKey: c.PublicKey, + Endpoint: c.Endpoint, + } + if c.Endpoint != nil { + ep := &net.UDPAddr{} + ip := c.Endpoint.IP + ep.IP = append(ip[:0:0], ip...) + ep.Port = c.Endpoint.Port + ep.Zone = c.Endpoint.Zone + peer.Endpoint = ep + } + for _, n := range c.AllowedIPs { + peer.AllowedIPs = append(peer.AllowedIPs, net.IPNet{ + IP: append(n.IP[:0:0], n.IP...), + Mask: append(n.Mask[:0:0], n.Mask...), + }) + } + f.peers[c.PublicKey] = peer + } + } + return nil +} +func getFakeClient() *client { + return &client{ + wgClient: &fakeWireGuardClient{}, + nodeName: "fake-node-1", + mtu: 1420, + listenPort: listenPort, + peerByNodeName: make(map[string]wgtypes.PeerConfig), + enabledIPv4: true, + enabledIPv6: false, + nodeIPv4: net.ParseIP("10.20.30.41"), + } +} + +func assertWgPeerAndPeerConfigIdentical(t *testing.T, peer wgtypes.Peer, peercfg wgtypes.PeerConfig) { + assert.EqualValues(t, peer.AllowedIPs, peercfg.AllowedIPs) + assert.EqualValues(t, peer.Endpoint, peercfg.Endpoint) + assert.EqualValues(t, peer.PublicKey, peercfg.PublicKey) +} + +func deepCopyForWireGuardPeer(peer wgtypes.Peer) wgtypes.Peer { + c := wgtypes.Peer{} + c.AllowedIPs = make([]net.IPNet, len(peer.AllowedIPs)) + for idx := range peer.AllowedIPs { + ip := peer.AllowedIPs[idx].IP + mask := peer.AllowedIPs[idx].Mask + c.AllowedIPs[idx].IP = append(ip[:0:0], ip...) + c.AllowedIPs[idx].Mask = append(mask[:0:0], mask...) + } + if peer.Endpoint != nil { + ep := &net.UDPAddr{} + ip := peer.Endpoint.IP + ep.IP = append(ip[:0:0], ip...) + ep.Port = peer.Endpoint.Port + ep.Zone = peer.Endpoint.Zone + c.Endpoint = ep + } + c.PublicKey = peer.PublicKey + return c +} + +func Test_RemoveStalePeers(t *testing.T) { + client := getFakeClient() + pk1, _ := wgtypes.GeneratePrivateKey() + pk2, _ := wgtypes.GeneratePrivateKey() + pk3, _ := wgtypes.GeneratePrivateKey() + t.Run("pass empty/nil slice should remove all existing peers", func(tt *testing.T) { + fc := &fakeWireGuardClient{ + peers: map[wgtypes.Key]wgtypes.Peer{ + pk1.PublicKey(): {PublicKey: pk1.PublicKey()}, + pk2.PublicKey(): {PublicKey: pk2.PublicKey()}, + }, + } + client.wgClient = fc + err := client.RemoveStalePeers(nil) + assert.Nil(tt, err) + assert.Empty(tt, fc.peers) + }) + + t.Run("args has no intersection with exsiting peers", func(tt *testing.T) { + fc := &fakeWireGuardClient{ + peers: map[wgtypes.Key]wgtypes.Peer{ + pk1.PublicKey(): {PublicKey: pk1.PublicKey()}, + pk2.PublicKey(): {PublicKey: pk2.PublicKey()}, + }, + } + client.wgClient = fc + err := client.RemoveStalePeers([]string{pk3.PublicKey().String()}) + assert.Nil(tt, err) + assert.Empty(tt, fc.peers) + }) + + t.Run("should only keep peer passed by args", func(tt *testing.T) { + fc := &fakeWireGuardClient{ + peers: map[wgtypes.Key]wgtypes.Peer{ + pk1.PublicKey(): {PublicKey: pk1.PublicKey()}, + pk2.PublicKey(): {PublicKey: pk2.PublicKey()}, + pk3.PublicKey(): {PublicKey: pk3.PublicKey()}, + }, + } + client.wgClient = fc + err := client.RemoveStalePeers([]string{pk3.PublicKey().String()}) + assert.Nil(tt, err) + assert.Len(tt, fc.peers, 1) + _, exist := fc.peers[pk3.PublicKey()] + assert.True(tt, exist) + }) +} + +func Test_UpdatePeer(t *testing.T) { + client := getFakeClient() + fc := &fakeWireGuardClient{ + peers: map[wgtypes.Key]wgtypes.Peer{}, + } + client.wgClient = fc + pk1, _ := wgtypes.GeneratePrivateKey() + pk2, _ := wgtypes.GeneratePrivateKey() + // pk3, _ := wgtypes.GeneratePrivateKey() + + ip1, ipnet1, _ := net.ParseCIDR("10.20.30.42/32") + ip2, ipnet2, _ := net.ParseCIDR("10.20.30.43/32") + peer1 := wgtypes.Peer{ + PublicKey: pk1.PublicKey(), + Endpoint: &net.UDPAddr{ + IP: ip1, + Port: listenPort, + }, + AllowedIPs: []net.IPNet{*ipnet1}, + } + + t.Run("call update peer to add new peers", func(tt *testing.T) { + err := client.UpdatePeer("fake-node-2", pk1.PublicKey().String(), ip1.To4(), nil) + assert.Nil(tt, err) + assert.Len(tt, fc.peers, 1) + assert.Len(tt, client.peerByNodeName, 1) + peerFromFakeClient, ok := fc.peers[pk1.PublicKey()] + assert.True(tt, ok) + assert.EqualValues(tt, peer1, peerFromFakeClient) + peerCfgFromClient, ok := client.peerByNodeName["fake-node-2"] + assert.True(tt, ok) + assertWgPeerAndPeerConfigIdentical(tt, peerFromFakeClient, peerCfgFromClient) + }) + + t.Run("call update peer to update existing peers", func(tt *testing.T) { + peer1Updated := wgtypes.Peer{ + PublicKey: pk2.PublicKey(), + Endpoint: &net.UDPAddr{ + IP: ip2, + Port: listenPort, + }, + AllowedIPs: []net.IPNet{*ipnet2}, + } + err := client.UpdatePeer("fake-node-2", pk2.PublicKey().String(), ip2.To4(), nil) + assert.Nil(tt, err) + assert.Len(tt, fc.peers, 1) + assert.Len(tt, client.peerByNodeName, 1) + peerFromFakeClient, ok := fc.peers[pk2.PublicKey()] + assert.True(tt, ok) + assert.EqualValues(tt, peer1Updated, peerFromFakeClient) + peerCfgFromClient, ok := client.peerByNodeName["fake-node-2"] + assert.True(tt, ok) + assertWgPeerAndPeerConfigIdentical(tt, peerFromFakeClient, peerCfgFromClient) + }) + + t.Run("call update peer with invalid public key", func(tt *testing.T) { + peerFromFakeClient, ok := fc.peers[pk2.PublicKey()] + assert.True(tt, ok) + peerFromFakeClientCopy := deepCopyForWireGuardPeer(peerFromFakeClient) + err := client.UpdatePeer("fake-node-2", "invalid key", ip1.To4(), nil) + assert.Error(tt, err) + assert.Len(tt, fc.peers, 1) + assert.Len(tt, client.peerByNodeName, 1) + peerFromFakeClientAfterUpdate, ok := fc.peers[pk2.PublicKey()] + assert.True(tt, ok) + assert.EqualValues(tt, peerFromFakeClientCopy, peerFromFakeClientAfterUpdate) + }) +} + +func Test_DeletePeer(t *testing.T) { + client := getFakeClient() + fc := &fakeWireGuardClient{ + peers: map[wgtypes.Key]wgtypes.Peer{}, + } + client.wgClient = fc + pk1, _ := wgtypes.GeneratePrivateKey() + ip1, _, _ := net.ParseCIDR("10.20.30.42/32") + t.Run("delete non-existing peer", func(tt *testing.T) { + err := client.UpdatePeer("fake-node-1", pk1.String(), ip1.To4(), nil) + assert.NoError(tt, err) + assert.Len(tt, fc.peers, 1) + assert.Len(tt, client.peerByNodeName, 1) + err = client.DeletePeer("fake-node-2") + assert.NoError(tt, err) + assert.Len(tt, fc.peers, 1) + assert.Len(tt, client.peerByNodeName, 1) + }) + + t.Run("delete existing peer", func(tt *testing.T) { + err := client.DeletePeer("fake-node-1") + assert.NoError(tt, err) + assert.Len(tt, fc.peers, 0) + assert.Len(tt, client.peerByNodeName, 0) + }) + +}