diff --git a/Makefile b/Makefile index 1359610..39dd5db 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,22 @@ pkg/debian-tuto2: pkg/debian-tuto2/sshd_config pkg/debian-tuto2/gai.conf pkg/deb linuxkit pkg build -org nemunaire pkg/debian-tuto2/ touch pkg/debian-tuto2 +pkg/debian-tuto3: pkg/debian-tuto3/sshd_config pkg/debian-tuto3/build.yml pkg/debian-tuto3/issue pkg/debian-tuto3/Dockerfile + linuxkit pkg build -org nemunaire pkg/debian-tuto3/ + touch pkg/debian-tuto3 + +pkg/router-tuto3: pkg/router-tuto3/build.yml pkg/router-tuto3/Dockerfile + linuxkit pkg build -org nemunaire pkg/router-tuto3/ + touch pkg/router-tuto3 + +pkg/tinydeb: pkg/tinydeb/sshd_config pkg/tinydeb/gai.conf pkg/tinydeb/build.yml pkg/tinydeb/Dockerfile + linuxkit pkg build -org nemunaire pkg/tinydeb/ + touch pkg/tinydeb + +pkg/nsd: pkg/nsd/sshd_config pkg/nsd/build.yml pkg/nsd/init pkg/nsd/Dockerfile + linuxkit pkg build -org nemunaire pkg/tinydeb/ + touch pkg/nsd + tuto2-kernel: tuto2.yml linuxkit build -docker $< tuto2-initrd.img: tuto2.yml @@ -75,8 +91,6 @@ tuto2-srs.iso: tuto2.iso pkg/debian-tuto2/isolinux.cfg sudo rm -rf $(TDIR) isohybrid $@ -tuto2-srs.iso.gz: tuto2-srs.iso - gzip -9 < $< > $@ tuto3-kernel: tuto3.yml linuxkit build -docker $< @@ -85,8 +99,12 @@ tuto3-initrd.img: tuto3.yml tuto3-cmdline: tuto3.yml linuxkit build -docker $< -tuto3.iso: tuto3.yml +tuto3.iso: tuto3.yml pkg/debian-tuto3 pkg/router-tuto3 pkg/tinydeb pkg/unbound pkg/nsd linuxkit build -docker -format iso-bios $< -tuto3.iso.gz: tuto3.iso + +%.gz: % gzip -9 < $< > $@ + +%.torrent: % + mktorrent -o $@ -a http://ankh.serekh.nemunai.re:6969/announce -p -v $< diff --git a/checker/checker.go b/checker/checker.go index a094070..656eb95 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -22,7 +22,10 @@ const ( year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. Taken from miekg/dns ) -var verbose = false +var ( + verbose = false + domainsHostingMap = map[string]string{} +) // ICMP @@ -48,13 +51,82 @@ func check_ping(ip string, cb func(pkt *ping.Packet)) (err error) { func get_GLUE(domain string) (aaaa net.IP, err error) { client := dns.Client{Net: "tcp", Timeout: time.Second * 5} + dnssrv := "[2a01:e0a:2b:2250::b]:53" + if strings.HasSuffix(domain, adlin.DelegatedDomainSuffix) { + dnssrv = "[2a01:e0a:2b:2250::b]:53" + } else if v, ok := domainsHostingMap[domain]; ok { + dnssrv = v + } else { + // Looking for root NS + m := new(dns.Msg) + m.SetQuestion(".", dns.TypeNS) + m.RecursionDesired = false + m.SetEdns0(4096, true) + + var r *dns.Msg + r, _, err = client.Exchange(m, dnssrv) + if err != nil { + return + } + + if r == nil { + return nil, errors.New("response is nil during initial recursion") + } + if r.Rcode != dns.RcodeSuccess { + return nil, errors.New("failed to get a valid answer during initial recursion") + } + + for _, answer := range r.Answer { + if t, ok := answer.(*dns.NS); ok { + dnssrv = t.Ns + ":53" + } + } + // Do casual recursion + i := 0 + recursion: + for i = 0; i < 10; i++ { + m := new(dns.Msg) + m.SetQuestion(domain, dns.TypeNS) + m.RecursionDesired = false + m.SetEdns0(4096, true) + + var r *dns.Msg + r, _, err = client.Exchange(m, dnssrv) + if err != nil { + return + } + + if r == nil { + return nil, errors.New("response is nil during recursion") + } + if r.Rcode != dns.RcodeSuccess { + return nil, errors.New("failed to get a valid answer during recursion") + } + + for _, answer := range r.Ns { + if t, ok := answer.(*dns.NS); ok { + dnssrv = t.Ns + ":53" + if t.Header().Name == domain { + break recursion + } + } + } + } + + if i >= 10 { + return nil, fmt.Errorf("too much name recursions") + } else { + domainsHostingMap[domain] = dnssrv + } + } + m := new(dns.Msg) m.SetQuestion(domain, dns.TypeNS) m.RecursionDesired = false m.SetEdns0(4096, true) var r *dns.Msg - r, _, err = client.Exchange(m, "[2a01:e0a:2b:2250::b]:53") + r, _, err = client.Exchange(m, dnssrv) if err != nil { return } @@ -450,6 +522,21 @@ func studentsChecker() { return } + // PingResolver + if tunnel_version == 3 { + tmp := strings.Split(stdIP, ":") + tmp[len(tmp)-1] = "2" + stdResolverIP := strings.Join(tmp, ":") + go check_ping(stdResolverIP, func(_ *ping.Packet) { + if verbose { + log.Printf("%s resolver PONG", std.Login) + } + if _, err := std.UnlockChallenge(CheckMap[tunnel_version][PingResolver], ""); err != nil { + log.Printf("Unable to register challenge for %s: %s\n", std.Login, err.Error()) + } + }) + } + dnsIP := stdIP var glueErr error // Is GLUE defined? @@ -484,7 +571,7 @@ func studentsChecker() { // Check HTTP with DNS if glueErr != nil { - std.RegisterChallengeError(100*(tunnel_version-1)+4, fmt.Errorf("Unable to perform the test due to GLUE problem: %w", err)) + std.RegisterChallengeError(100*(tunnel_version-1)+4, fmt.Errorf("Unable to perform the test due to GLUE problem: %w", glueErr)) } else if err := check_http(addr.String(), std.MyDelegatedDomain()); err == nil { if verbose { log.Printf("%s just unlocked HTTP challenge\n", std.Login) @@ -501,7 +588,7 @@ func studentsChecker() { // Check HTTPs with DNS if glueErr != nil { - std.RegisterChallengeError(100*(tunnel_version-1)+5, fmt.Errorf("Unable to perform the test due to GLUE problem: %w", err)) + std.RegisterChallengeError(100*(tunnel_version-1)+5, fmt.Errorf("Unable to perform the test due to GLUE problem: %w", glueErr)) } else if err := check_https(std.MyDelegatedDomain(), addr.String()); err == nil { if verbose { log.Printf("%s just unlocked HTTPS challenge\n", std.Login) @@ -564,11 +651,11 @@ func studentsChecker() { if verbose { log.Printf("%s just unlocked HTTP IP (without DNS) challenge\n", std.Login) } - if _, err := std.UnlockChallenge(100*(tunnel_version-1)+0, ""); err != nil { + if _, err := std.UnlockChallenge(CheckMap[tunnel_version][HTTPonIP], ""); err != nil { log.Printf("Unable to register challenge for %s: %s\n", std.Login, err.Error()) } } else { - std.RegisterChallengeError(100*(tunnel_version-1)+0, err) + std.RegisterChallengeError(CheckMap[tunnel_version][HTTPonIP], err) if verbose { log.Printf("%s and HTTP IP (without DNS): %s\n", std.Login, err) } diff --git a/checker/checks.go b/checker/checks.go new file mode 100644 index 0000000..105b7c8 --- /dev/null +++ b/checker/checks.go @@ -0,0 +1,47 @@ +package main + +type AdlinTest int + +const ( + HTTPonIP AdlinTest = iota + HTTPonAssociatedDomain + HTTPSonAssociatedDomain + DNSDelegation + HTTPonDelegatedDomain + HTTPSonDelegatedDomain + Matrix + SNI + DNSSEC + PingResolver + DHCPonRH + DHCPonGuests + RHaccessNews + RHaccessNet + GuestNet +) + +var CheckMap = map[int]map[AdlinTest]int{ + 2: map[AdlinTest]int{ + HTTPonIP: 100, + HTTPonAssociatedDomain: 101, + HTTPSonAssociatedDomain: 102, + DNSDelegation: 103, + HTTPonDelegatedDomain: 104, + HTTPSonDelegatedDomain: 105, + Matrix: 106, + DNSSEC: 107, + }, + 3: map[AdlinTest]int{ + PingResolver: 200, + HTTPonIP: 201, + DNSDelegation: 203, + HTTPonDelegatedDomain: 204, + HTTPSonDelegatedDomain: 205, + Matrix: 206, + DHCPonRH: 208, + DHCPonGuests: 211, + RHaccessNews: 209, + RHaccessNet: 210, + GuestNet: 212, + }, +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..14b8415 --- /dev/null +++ b/go.mod @@ -0,0 +1,19 @@ +module git.nemunai.re/lectures/adlin + +go 1.16 + +require ( + github.com/coreos/go-oidc v2.2.1+incompatible + github.com/gdamore/tcell v1.4.0 + github.com/go-sql-driver/mysql v1.5.0 + github.com/jcmturner/gokrb5/v8 v8.4.2 + github.com/julienschmidt/httprouter v1.3.0 + github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc + github.com/miekg/dns v1.1.41 + github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect + github.com/rivo/tview v0.0.0-20210312174852-ae9464cc3598 + golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84 + gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect + gopkg.in/ldap.v2 v2.5.1 + gopkg.in/square/go-jose.v2 v2.5.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..36fd57c --- /dev/null +++ b/go.sum @@ -0,0 +1,440 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= +github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU= +github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0= +github.com/gdamore/tcell/v2 v2.2.0 h1:vSyEgKwraXPSOkvCk7IwOSyX+Pv3V2cV9CikJMXg4U4= +github.com/gdamore/tcell/v2 v2.2.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= +github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= +github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.2 h1:6ZIM6b/JJN0X8UM43ZOM6Z4SJzla+a/u7scXFJzodkA= +github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc= +github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc h1:m7rJJJeXrYCFpsxXYapkDW53wJCDmf9bsIXUg0HoeQY= +github.com/mdlayher/arp v0.0.0-20191213142603-f72070a231fc/go.mod h1:eOj1DDj3NAZ6yv+WafaKzY37MFZ58TdfIhQ+8nQbiis= +github.com/mdlayher/ethernet v0.0.0-20190313224307-5b5fc417d966 h1:O3p5UmisBhl3V6lgs4Vdfg8HpjzbWJPyOfGLdwVJSmI= +github.com/mdlayher/ethernet v0.0.0-20190313224307-5b5fc417d966/go.mod h1:5s5p/sMJ6sNsFl6uCh85lkFGV8kLuIYJCRJLavVJwvg= +github.com/mdlayher/raw v0.0.0-20190313224157-43dbcdd7739d h1:rjAS0af7FIYCScTtEU5KjIldC6qVaEScUJhABHC+ccM= +github.com/mdlayher/raw v0.0.0-20190313224157-43dbcdd7739d/go.mod h1:r1fbeITl2xL/zLbVnNHFyOzQJTgr/3fpf1lJX/cjzR8= +github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac h1:jWKYCNlX4J5s8M0nHYkh7Y7c9gRVDEb3mq51j5J0F5M= +github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rivo/tview v0.0.0-20210312174852-ae9464cc3598 h1:AbRrGXhagPRDItERv7nauBUUPi7Ma3IGIj9FqkQKW6k= +github.com/rivo/tview v0.0.0-20210312174852-ae9464cc3598/go.mod h1:VzCN9WX13RF88iH2CaGkmdHOlsy1ZZQcTmNwROqC+LI= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +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/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU= +golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +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= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +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= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84 h1:duBc5zuJsmJXYOVVE/6PxejI+N3AaCqKjtsoLn1Je5Q= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +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-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-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +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= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +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= +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= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU= +gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/libadlin/db.go b/libadlin/db.go index 5fafcc9..cfa149b 100644 --- a/libadlin/db.go +++ b/libadlin/db.go @@ -114,8 +114,10 @@ CREATE TABLE IF NOT EXISTS student_challenge_errors( if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS student_pong( id_student INTEGER NOT NULL, - time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + last TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + count INTEGER UNSIGNED DEFAULT 1, state BOOLEAN NOT NULL DEFAULT 0, + CONSTRAINT one_pong UNIQUE (id_student,state), FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; `); err != nil { diff --git a/libadlin/ping.go b/libadlin/ping.go index a93fc9c..9926a87 100644 --- a/libadlin/ping.go +++ b/libadlin/ping.go @@ -6,18 +6,19 @@ import ( type Pong struct { Date time.Time + Count uint State bool } func (s *Student) LastPongs() (pongs []*Pong, err error) { - if rows, errr := DBQuery("SELECT time, state FROM student_pong WHERE id_student = ? ORDER BY time DESC", s.Id); errr != nil { + if rows, errr := DBQuery("SELECT last, count, state FROM student_pong WHERE id_student = ? ORDER BY last DESC", s.Id); errr != nil { return nil, errr } else { defer rows.Close() for rows.Next() { p := &Pong{} - if err = rows.Scan(&p.Date, &p.State); err != nil { + if err = rows.Scan(&p.Date, &p.Count, &p.State); err != nil { return } pongs = append(pongs, p) @@ -31,6 +32,9 @@ func (s *Student) LastPongs() (pongs []*Pong, err error) { } func (s *Student) OnPong(state bool) (err error) { - _, err = DBExec("INSERT INTO student_pong (id_student, time, state) VALUES (?, ?, ?)", s.Id, time.Now(), state) + _, err = DBExec("INSERT INTO student_pong (id_student, last, state) VALUES (?, ?, ?)", s.Id, time.Now(), state) + if err != nil { + _, err = DBExec("UPDATE student_pong SET last = CURRENT_TIMESTAMP, count = count + 1 WHERE id_student = ? AND state = ?", s.Id, state) + } return } diff --git a/libadlin/tunnel.go b/libadlin/tunnel.go index c22a520..c4fa99c 100644 --- a/libadlin/tunnel.go +++ b/libadlin/tunnel.go @@ -1,6 +1,7 @@ package adlin import ( + "crypto/ed25519" "crypto/rand" "crypto/sha512" "encoding/base64" @@ -14,6 +15,18 @@ import ( const StdNetmask = 80 +var ( + collector_secret ed25519.PrivateKey +) + +func SetCollectorSecret(b []byte) { + collector_secret = ed25519.NewKeyFromSeed(b) +} + +func GetCollectorPublic() ed25519.PublicKey { + return collector_secret.Public().(ed25519.PublicKey) +} + func StudentIP(idstd int64) net.IP { return net.ParseIP(fmt.Sprintf("2a01:e0a:2b:2252:%x::", idstd)) } @@ -36,6 +49,10 @@ type WGDump struct { KeepAlive string } +func (d *WGDump) GetPubKey() ([]byte, error) { + return base64.StdEncoding.DecodeString(d.PubKey) +} + var ( wgDumpCache_data map[string]*WGDump = nil wgDumpCache_time time.Time @@ -111,6 +128,14 @@ func (tt *TunnelToken) GetStudentIP() string { } } +func (tt *TunnelToken) GenKeySign() []byte { + stdprivkey := ed25519.NewKeyFromSeed(tt.token[:ed25519.SeedSize]) + + stdpublic := []byte(stdprivkey.Public().(ed25519.PublicKey)) + + return ed25519.Sign(collector_secret, stdpublic) +} + func TokenFromText(token string) []byte { sha := sha512.Sum512([]byte(token)) return sha[:] @@ -200,6 +225,23 @@ func (student *Student) GetActivesTunnels() (ts []*TunnelToken, err error) { } } +func (student *Student) GetActivesTunnelsPubKey() (ts []ed25519.PublicKey, err error) { + var activeTuns []*TunnelToken + activeTuns, err = student.GetActivesTunnels() + if err != nil { + return + } + + for _, tun := range activeTuns { + if tun.Dump != nil { + pk := ed25519.NewKeyFromSeed(tun.token[:ed25519.SeedSize]) + ts = append(ts, pk.Public().(ed25519.PublicKey)) + } + } + + return +} + func (student *Student) GetTunnelToken(token []byte) (t *TunnelToken, err error) { t = new(TunnelToken) err = DBQueryRow("SELECT token, token_text, id_student, pubkey, time, suffixip, version FROM student_tunnel_tokens WHERE token = ? AND id_student = ? ORDER BY time DESC", token, student.Id).Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.Version) diff --git a/pkg/minichecker/Dockerfile b/pkg/minichecker/Dockerfile new file mode 100644 index 0000000..983882d --- /dev/null +++ b/pkg/minichecker/Dockerfile @@ -0,0 +1,23 @@ +FROM golang:alpine as gobuild + +ENV GOOS linux +ENV GOARCH amd64 + +RUN apk add --no-cache git gcc + +WORKDIR /go/src/minichecker + +ADD cmd ./ + +RUN GO111MODULE=off go get -d -v +RUN GO111MODULE=off go build -v -tags netgo + + +FROM alpine +MAINTAINER Pierre-Olivier Mercier + +COPY --from=gobuild /go/src/minichecker/minichecker /bin/minichecker + +RUN mkdir /etc/wireguard && touch /etc/wireguard/.wireguard + +ENTRYPOINT ["/bin/minichecker"] diff --git a/pkg/minichecker/build.yml b/pkg/minichecker/build.yml new file mode 100644 index 0000000..3a00da6 --- /dev/null +++ b/pkg/minichecker/build.yml @@ -0,0 +1,2 @@ +image: minichecker +network: true diff --git a/pkg/minichecker/cmd/adlin.conf b/pkg/minichecker/cmd/adlin.conf new file mode 100644 index 0000000..a357b3f --- /dev/null +++ b/pkg/minichecker/cmd/adlin.conf @@ -0,0 +1,12 @@ +[Interface] +PrivateKey = AKZx4pYq2Do2j/OOFFJ6eA/O7DiAkr6aINJRHdMnkVU= +[Peer] +PublicKey = uSpqyYovvP4OG6wDxZ0Qkq45MfyK58PMUuPaLesY8FI= +Endpoint = 82.64.31.248:42912 +AllowedIPs = ::/0 +PersistentKeepalive = 5 +# MyIPv6=2a01:e0a:2b:2252:1::2a/64 +# MyNetwork=2a01:e0a:2b:2252:1::/80 +# GWIPv6=2a01:e0a:2b:2252::1 +# MyLogin=nemunaire +# KeySign=lcUxw+Gw+m9q21yvAL5BJJ9xpACTefeyR6qBsBFPyO9lqtrq/qqWAvf/gITtXdNmRne4FU72pw9pzL2J8SVeAw== diff --git a/pkg/minichecker/cmd/adlin.token b/pkg/minichecker/cmd/adlin.token new file mode 100644 index 0000000..e167a75 --- /dev/null +++ b/pkg/minichecker/cmd/adlin.token @@ -0,0 +1 @@ +QMzkCN3PPg \ No newline at end of file diff --git a/pkg/minichecker/cmd/checker.go b/pkg/minichecker/cmd/checker.go new file mode 100644 index 0000000..dba6214 --- /dev/null +++ b/pkg/minichecker/cmd/checker.go @@ -0,0 +1,169 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "log" + "net" + "net/http" + "strings" + "time" + + "github.com/miekg/dns" + "github.com/sparrc/go-ping" +) + +const ( + DEFAULT_RESOLVER = "2a01:e0a:2b:2250::1" +) + +var ( + verbose = false + test_name = "" +) + +// ICMP + +func check_ping(ip string, cb func(pkt *ping.Packet)) (err error) { + var pinger *ping.Pinger + pinger, err = ping.NewPinger(ip) + if err != nil { + return + } + defer pinger.Stop() + + pinger.Timeout = time.Second * 5 + pinger.Count = 1 + pinger.OnRecv = cb + pinger.SetPrivileged(true) + pinger.Run() + + return +} + +func check_dns(domain, ip string) (aaaa net.IP, err error) { + client := dns.Client{Timeout: time.Second * 5} + + m := new(dns.Msg) + m.SetQuestion(domain, dns.TypeAAAA) + + var r *dns.Msg + r, _, err = client.Exchange(m, fmt.Sprintf("[%s]:53", ip)) + if err != nil { + return + } + + if r == nil { + err = errors.New("response is nil") + return + } + if r.Rcode != dns.RcodeSuccess { + err = errors.New("failed to get a valid answer") + return + } + + for _, answer := range r.Answer { + if t, ok := answer.(*dns.AAAA); ok { + aaaa = t.AAAA + } + } + + return +} + +// PORT 80 + +func check_http(ip, dn string) (err error) { + client := &http.Client{ + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return http.ErrUseLastResponse + }, + } + + req, errr := http.NewRequest("GET", fmt.Sprintf("http://[%s]/", ip), nil) + if errr != nil { + return errr + } + + if dn != "" { + req.Header.Add("Host", strings.TrimSuffix(dn, ".")) + } + + var resp *http.Response + resp, err = client.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + + if dn != "" && resp.StatusCode >= 400 { + return fmt.Errorf("Bad status, got: %d (%s)", resp.StatusCode, resp.Status) + } + + _, err = ioutil.ReadAll(resp.Body) + return +} + +// PORT 443 + +func check_https(domain, ip string) (err error) { + var resp *http.Response + resp, err = http.Get(fmt.Sprintf("https://%s/", strings.TrimSuffix(domain, "."))) + if err != nil { + return + } + defer resp.Body.Close() + + if resp.StatusCode >= 300 && resp.StatusCode < 400 { + loc := resp.Header.Get("Location") + if loc != "" && strings.HasSuffix(dns.Fqdn(loc), domain) { + if dns.Fqdn(loc) == domain { + return fmt.Errorf("Redirection loop %s redirect to %s", domain, loc) + } else if err = check_https(dns.Fqdn(loc), ip); err != nil { + return fmt.Errorf("Error after following redirection to %s: %w", loc, err) + } else { + return + } + } + } + + if resp.StatusCode >= 300 { + return fmt.Errorf("Bad status, got: %d (%s)", resp.StatusCode, resp.Status) + } + + _, err = ioutil.ReadAll(resp.Body) + return +} + +func wksChecker() { + if collectorpubkey == nil { + var err error + if collectorpubkey, err = getCollectorPublicKey(); err != nil { + log.Println("Contact collector:", err) + return + } + } + + data, err := encodeData(SendMeta{Login: Login}, map[string]*string{ + test_name: nil, + }) + if err != nil { + log.Println("Unable to encode message:", err) + return + } + + err = sendData(data) + if err != nil { + log.Println("Unable to send message:", err) + return + } + + v, _ := json.Marshal(data) + if verbose { + log.Printf("sent %s", v) + } + + return +} diff --git a/pkg/minichecker/cmd/encode.go b/pkg/minichecker/cmd/encode.go new file mode 100644 index 0000000..8cd0ef3 --- /dev/null +++ b/pkg/minichecker/cmd/encode.go @@ -0,0 +1,83 @@ +package main + +import ( + "bytes" + "crypto/ed25519" + "encoding/base64" + "encoding/json" + "io/ioutil" + "net/http" + "time" +) + +var ( + Login string + KeySign string + target string +) + +func getCollectorPublicKey() (key []byte, err error) { + var resp *http.Response + resp, err = http.Get(target + "/api/collector_info") + if err != nil { + return + } + + defer resp.Body.Close() + + rd := base64.NewDecoder(base64.StdEncoding, json.NewDecoder(resp.Body).Buffered()) + return ioutil.ReadAll(rd) +} + +type SendMeta struct { + Time time.Time `json:"time"` + Login string `json:"login"` + Test string `json:"test,omitempty"` +} + +type SendContent struct { + Meta []byte `json:"meta"` + Data []byte `json:"data"` + Sign []byte `json:"sign"` + Key []byte `json:"key"` + KeySign string `json:"keysign"` +} + +func encodeData(meta SendMeta, v interface{}) (data SendContent, err error) { + if meta.Time.IsZero() { + meta.Time = time.Now() + } + var b []byte + b, err = json.Marshal(meta) + if err != nil { + return + } + data.Meta = []byte(base64.StdEncoding.EncodeToString(b)) + + b, err = json.Marshal(v) + if err != nil { + return + } + data.Data = []byte(base64.StdEncoding.EncodeToString(b)) + + data.Sign = ed25519.Sign(myprivkey, append(data.Meta, data.Data...)) + data.Key = myprivkey.Public().(ed25519.PublicKey) + data.KeySign = KeySign + + return +} + +func sendData(data SendContent) (err error) { + b := new(bytes.Buffer) + json.NewEncoder(b).Encode(data) + + var resp *http.Response + resp, err = http.Post(target+"/remote", "application/json", b) + if err != nil { + return + } + + resp.Body.Close() + + return +} diff --git a/pkg/minichecker/cmd/go.mod b/pkg/minichecker/cmd/go.mod new file mode 100644 index 0000000..4b10de3 --- /dev/null +++ b/pkg/minichecker/cmd/go.mod @@ -0,0 +1 @@ +module example.com/mod diff --git a/pkg/minichecker/cmd/main.go b/pkg/minichecker/cmd/main.go new file mode 100644 index 0000000..f485cbf --- /dev/null +++ b/pkg/minichecker/cmd/main.go @@ -0,0 +1,152 @@ +package main + +import ( + "bytes" + "crypto/ed25519" + "crypto/sha512" + "flag" + "io/ioutil" + "log" + "math/rand" + "os" + "os/signal" + "path" + "syscall" + "time" + + "gopkg.in/fsnotify.v1" +) + +var ( + myprivkey ed25519.PrivateKey + collectorpubkey ed25519.PublicKey +) + +func main() { + var tokenfile = flag.String("token-file", "/etc/wireguard/adlin.token", "Path to your token file") + var wgfile = flag.String("wg-file", "/etc/wireguard/adlin.conf", "Path to your wireguard configuration file") + var interval = flag.Duration("check-interval", 30*time.Second, "Interval between two checks") + flag.StringVar(&test_name, "test-name", "", "Name of the test to report") + flag.StringVar(&target, "target", "https://adlin.nemunai.re", "HTTP server to contact") + flag.BoolVar(&verbose, "verbose", verbose, "Enable verbose mode") + flag.Parse() + + if test_name == "" { + test_name, _ = os.Hostname() + } + + // First load token if it exists + if _, err := os.Stat(*tokenfile); !os.IsNotExist(err) { + if err := loadToken(*tokenfile); err != nil { + log.Fatal("ERROR: Unable to read token file:", err) + } + } else { + log.Fatal("Unable to find token file:", err) + } + + // Load of configuration if it exists + if _, err := os.Stat(*wgfile); !os.IsNotExist(err) { + if err := loadSettings(*wgfile); err != nil { + log.Println("ERROR: Unable to read wg settings:", err) + } + } + + // Register SIGHUP + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGHUP) + go func() { + for range c { + log.Println("SIGHUP received, reloading settings...") + if err := loadSettings(*wgfile); err != nil { + log.Println("ERROR: Unable to read wg settings:", err) + } + } + }() + + // Watch the configuration file + if watcher, err := fsnotify.NewWatcher(); err != nil { + log.Fatal(err) + } else { + if err := watcher.Add(path.Dir(*wgfile)); err != nil { + log.Fatal("Unable to watch: ", path.Dir(*wgfile), ": ", err) + } + + go func() { + defer watcher.Close() + for { + select { + case ev := <-watcher.Events: + if path.Base(ev.Name) == *wgfile && ev.Op&(fsnotify.Write|fsnotify.Create) != 0 { + log.Println("Settings file changes, reloading it!") + if err := loadSettings(*wgfile); err != nil { + log.Println("ERROR: Unable to read wg settings:", err) + } + } + case err := <-watcher.Errors: + log.Println("watcher error:", err) + } + } + }() + } + + // Prepare graceful shutdown + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) + + // Delay first check randomly + rand.Seed(time.Now().UnixNano()) + n := rand.Intn(10) + time.Sleep(time.Duration(n) * time.Second) + + ticker := time.NewTicker(*interval) + defer ticker.Stop() + + // Launch checker + //wksChecker() +loop: + for { + select { + case <-interrupt: + break loop + case <-ticker.C: + wksChecker() + } + } + +} + +func loadToken(filename string) error { + if fd, err := os.Open(filename); err != nil { + return err + } else { + defer fd.Close() + + if b, err := ioutil.ReadAll(fd); err != nil { + return err + } else { + seed := sha512.Sum512(bytes.TrimSpace(b)) + myprivkey = ed25519.NewKeyFromSeed(seed[:ed25519.SeedSize]) + } + + return nil + } +} + +func loadSettings(filename string) error { + if fd, err := os.Open(filename); err != nil { + return err + } else { + defer fd.Close() + + if b, err := ioutil.ReadAll(fd); err != nil { + return err + } else if wgConf, err := FromWgQuick(string(b), "wg0"); err != nil { + return err + } else { + Login = wgConf.Interface.MyLogin + KeySign = wgConf.Interface.KeySign + } + + return nil + } +} diff --git a/pkg/minichecker/cmd/wg.go b/pkg/minichecker/cmd/wg.go new file mode 100644 index 0000000..74d01f0 --- /dev/null +++ b/pkg/minichecker/cmd/wg.go @@ -0,0 +1,409 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved. + * + * From https://git.zx2c4.com/wireguard-windows/conf/ + */ +package main + +import ( + "crypto/subtle" + "encoding/base64" + "encoding/hex" + "fmt" + "net" + "strconv" + "strings" + "time" +) + +const KeyLength = 32 + +type IPCidr struct { + IP net.IP + Cidr uint8 +} + +type Endpoint struct { + Host string + Port uint16 +} + +type Key [KeyLength]byte +type HandshakeTime time.Duration +type Bytes uint64 + +type Config struct { + Name string + Interface Interface + Peers []Peer +} + +type Interface struct { + PrivateKey Key + MyLogin string + KeySign string + Addresses []IPCidr + ListenPort uint16 + MTU uint16 + DNS []net.IP + DNSSearch []string + PreUp string + PostUp string + PreDown string + PostDown string +} + +type Peer struct { + PublicKey Key + PresharedKey Key + AllowedIPs []IPCidr + Endpoint Endpoint + PersistentKeepalive uint16 + + RxBytes Bytes + TxBytes Bytes + LastHandshakeTime HandshakeTime +} + +func (k *Key) IsZero() bool { + var zeros Key + return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1 +} + +type ParseError struct { + why string + offender string +} + +func (e *ParseError) Error() string { + return fmt.Sprintf("%s: %q", e.why, e.offender) +} + +func parseIPCidr(s string) (ipcidr *IPCidr, err error) { + var addrStr, cidrStr string + var cidr int + + i := strings.IndexByte(s, '/') + if i < 0 { + addrStr = s + } else { + addrStr, cidrStr = s[:i], s[i+1:] + } + + err = &ParseError{fmt.Sprintf("Invalid IP address"), s} + addr := net.ParseIP(addrStr) + if addr == nil { + return + } + maybeV4 := addr.To4() + if maybeV4 != nil { + addr = maybeV4 + } + if len(cidrStr) > 0 { + err = &ParseError{fmt.Sprintf("Invalid network prefix length"), s} + cidr, err = strconv.Atoi(cidrStr) + if err != nil || cidr < 0 || cidr > 128 { + return + } + if cidr > 32 && maybeV4 != nil { + return + } + } else { + if maybeV4 != nil { + cidr = 32 + } else { + cidr = 128 + } + } + return &IPCidr{addr, uint8(cidr)}, nil +} + +func parseEndpoint(s string) (*Endpoint, error) { + i := strings.LastIndexByte(s, ':') + if i < 0 { + return nil, &ParseError{fmt.Sprintf("Missing port from endpoint"), s} + } + host, portStr := s[:i], s[i+1:] + if len(host) < 1 { + return nil, &ParseError{fmt.Sprintf("Invalid endpoint host"), host} + } + port, err := parsePort(portStr) + if err != nil { + return nil, err + } + hostColon := strings.IndexByte(host, ':') + if host[0] == '[' || host[len(host)-1] == ']' || hostColon > 0 { + err := &ParseError{fmt.Sprintf("Brackets must contain an IPv6 address"), host} + if len(host) > 3 && host[0] == '[' && host[len(host)-1] == ']' && hostColon > 0 { + end := len(host) - 1 + if i := strings.LastIndexByte(host, '%'); i > 1 { + end = i + } + maybeV6 := net.ParseIP(host[1:end]) + if maybeV6 == nil || len(maybeV6) != net.IPv6len { + return nil, err + } + } else { + return nil, err + } + host = host[1 : len(host)-1] + } + return &Endpoint{host, uint16(port)}, nil +} + +func parseMTU(s string) (uint16, error) { + m, err := strconv.Atoi(s) + if err != nil { + return 0, err + } + if m < 576 || m > 65535 { + return 0, &ParseError{fmt.Sprintf("Invalid MTU"), s} + } + return uint16(m), nil +} + +func parsePort(s string) (uint16, error) { + m, err := strconv.Atoi(s) + if err != nil { + return 0, err + } + if m < 0 || m > 65535 { + return 0, &ParseError{fmt.Sprintf("Invalid port"), s} + } + return uint16(m), nil +} + +func parsePersistentKeepalive(s string) (uint16, error) { + if s == "off" { + return 0, nil + } + m, err := strconv.Atoi(s) + if err != nil { + return 0, err + } + if m < 0 || m > 65535 { + return 0, &ParseError{fmt.Sprintf("Invalid persistent keepalive"), s} + } + return uint16(m), nil +} + +func parseKeyBase64(s string) (*Key, error) { + k, err := base64.StdEncoding.DecodeString(s) + if err != nil { + return nil, &ParseError{fmt.Sprintf("Invalid key: %v", err), s} + } + if len(k) != KeyLength { + return nil, &ParseError{fmt.Sprintf("Keys must decode to exactly 32 bytes"), s} + } + var key Key + copy(key[:], k) + return &key, nil +} + +func parseKeyHex(s string) (*Key, error) { + k, err := hex.DecodeString(s) + if err != nil { + return nil, &ParseError{fmt.Sprintf("Invalid key: %v", err), s} + } + if len(k) != KeyLength { + return nil, &ParseError{fmt.Sprintf("Keys must decode to exactly 32 bytes"), s} + } + var key Key + copy(key[:], k) + return &key, nil +} + +func parseBytesOrStamp(s string) (uint64, error) { + b, err := strconv.ParseUint(s, 10, 64) + if err != nil { + return 0, &ParseError{fmt.Sprintf("Number must be a number between 0 and 2^64-1: %v", err), s} + } + return b, nil +} + +func splitList(s string) ([]string, error) { + var out []string + for _, split := range strings.Split(s, ",") { + trim := strings.TrimSpace(split) + if len(trim) == 0 { + return nil, &ParseError{fmt.Sprintf("Two commas in a row"), s} + } + out = append(out, trim) + } + return out, nil +} + +type parserState int + +const ( + inInterfaceSection parserState = iota + inPeerSection + notInASection +) + +func (c *Config) maybeAddPeer(p *Peer) { + if p != nil { + c.Peers = append(c.Peers, *p) + } +} + +func FromWgQuick(s string, name string) (*Config, error) { + lines := strings.Split(s, "\n") + parserState := notInASection + conf := Config{Name: name} + sawPrivateKey := false + var peer *Peer + for _, line := range lines { + pound := strings.IndexByte(line, '#') + if pound >= 0 { + if !strings.Contains(line, "MyLogin") && !strings.Contains(line, "KeySign") { + line = line[:pound] + } else { + line = line[pound+1:] + } + } + line = strings.TrimSpace(line) + lineLower := strings.ToLower(line) + if len(line) == 0 { + continue + } + if lineLower == "[interface]" { + conf.maybeAddPeer(peer) + parserState = inInterfaceSection + continue + } + if lineLower == "[peer]" { + conf.maybeAddPeer(peer) + peer = &Peer{} + parserState = inPeerSection + continue + } + if parserState == notInASection { + return nil, &ParseError{fmt.Sprintf("Line must occur in a section"), line} + } + equals := strings.IndexByte(line, '=') + if equals < 0 { + return nil, &ParseError{fmt.Sprintf("Config key is missing an equals separator"), line} + } + key, val := strings.TrimSpace(lineLower[:equals]), strings.TrimSpace(line[equals+1:]) + if len(val) == 0 { + return nil, &ParseError{fmt.Sprintf("Key must have a value"), line} + } + if parserState == inInterfaceSection { + switch key { + case "privatekey": + k, err := parseKeyBase64(val) + if err != nil { + return nil, err + } + conf.Interface.PrivateKey = *k + sawPrivateKey = true + case "listenport": + p, err := parsePort(val) + if err != nil { + return nil, err + } + conf.Interface.ListenPort = p + case "mtu": + m, err := parseMTU(val) + if err != nil { + return nil, err + } + conf.Interface.MTU = m + case "address": + addresses, err := splitList(val) + if err != nil { + return nil, err + } + for _, address := range addresses { + a, err := parseIPCidr(address) + if err != nil { + return nil, err + } + conf.Interface.Addresses = append(conf.Interface.Addresses, *a) + } + case "dns": + addresses, err := splitList(val) + if err != nil { + return nil, err + } + for _, address := range addresses { + a := net.ParseIP(address) + if a == nil { + conf.Interface.DNSSearch = append(conf.Interface.DNSSearch, address) + } else { + conf.Interface.DNS = append(conf.Interface.DNS, a) + } + } + case "preup": + conf.Interface.PreUp = val + case "postup": + conf.Interface.PostUp = val + case "predown": + conf.Interface.PreDown = val + case "postdown": + conf.Interface.PostDown = val + default: + return nil, &ParseError{fmt.Sprintf("Invalid key for [Interface] section"), key} + } + } else if parserState == inPeerSection { + switch key { + case "publickey": + k, err := parseKeyBase64(val) + if err != nil { + return nil, err + } + peer.PublicKey = *k + case "presharedkey": + k, err := parseKeyBase64(val) + if err != nil { + return nil, err + } + peer.PresharedKey = *k + case "allowedips": + addresses, err := splitList(val) + if err != nil { + return nil, err + } + for _, address := range addresses { + a, err := parseIPCidr(address) + if err != nil { + return nil, err + } + peer.AllowedIPs = append(peer.AllowedIPs, *a) + } + case "persistentkeepalive": + p, err := parsePersistentKeepalive(val) + if err != nil { + return nil, err + } + peer.PersistentKeepalive = p + case "endpoint": + e, err := parseEndpoint(val) + if err != nil { + return nil, err + } + peer.Endpoint = *e + case "mylogin": + conf.Interface.MyLogin = val + case "keysign": + conf.Interface.KeySign = val + default: + return nil, &ParseError{fmt.Sprintf("Invalid key for [Peer] section"), key} + } + } + } + conf.maybeAddPeer(peer) + + if !sawPrivateKey { + return nil, &ParseError{fmt.Sprintf("An interface must have a private key"), fmt.Sprintf("[none specified]")} + } + for _, p := range conf.Peers { + if p.PublicKey.IsZero() { + return nil, &ParseError{fmt.Sprintf("All peers must have public keys"), fmt.Sprintf("[none specified]")} + } + } + + return &conf, nil +} diff --git a/pkg/router-tuto3/Dockerfile b/pkg/router-tuto3/Dockerfile new file mode 100644 index 0000000..942dd1b --- /dev/null +++ b/pkg/router-tuto3/Dockerfile @@ -0,0 +1,14 @@ +FROM openwrtorg/rootfs:x86-64-19.07.7 + +RUN mkdir -p /var/lock/ && opkg update && opkg install \ + bind-dig \ + curl \ + ethtool \ + luci-proto-wireguard \ + nano \ + ssmtp \ + python \ + tcpdump \ + && rm -rf /var/lock \ + && rm -rf /etc/ssh/ssh_host_*_key* \ + && echo "alias ip='ip -c'" >> /etc/profile diff --git a/pkg/router-tuto3/build.yml b/pkg/router-tuto3/build.yml new file mode 100644 index 0000000..4da7442 --- /dev/null +++ b/pkg/router-tuto3/build.yml @@ -0,0 +1,2 @@ +image: router-tuto3 +network: true diff --git a/pkg/unbound/Dockerfile b/pkg/unbound/Dockerfile index d6ddbee..5101097 100644 --- a/pkg/unbound/Dockerfile +++ b/pkg/unbound/Dockerfile @@ -1,15 +1,17 @@ FROM alpine MAINTAINER Pierre-Olivier Mercier -RUN apk add --no-cache unbound dnssec-root -COPY docker-entrypoint.sh / +RUN apk add --no-cache alpine-baselayout bash busybox unbound unbound-openrc dnssec-root openssh openrc VOLUME /etc/unbound EXPOSE 53 EXPOSE 53/udp -ENTRYPOINT ["/docker-entrypoint.sh"] -CMD ["/usr/sbin/unbound", "-d"] +RUN unbound-anchor && mkdir -p /var/log && touch /var/log/unbound.log && chown unbound:unbound /var/log/unbound.log +RUN rc-update add unbound default && rc-update add sshd default && rc-update add networking default +COPY sshd_config /etc/ssh/sshd_config + +CMD ["/sbin/openrc-init"] LABEL org.mobyproject.config='{"binds": ["/etc/resolv.conf:/etc/resolv.conf"], "capabilities": ["CAP_NET_BIND_SERVICE"]}' diff --git a/pkg/unbound/sshd_config b/pkg/unbound/sshd_config new file mode 100644 index 0000000..982d908 --- /dev/null +++ b/pkg/unbound/sshd_config @@ -0,0 +1,104 @@ +# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $ + +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented. Uncommented options override the +# default value. + +#Port 22 +#AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: + +#HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_ecdsa_key +#HostKey /etc/ssh/ssh_host_ed25519_key + +# Ciphers and keying +#RekeyLimit default none + +# Logging +#SyslogFacility AUTH +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin yes +#StrictModes yes +#MaxAuthTries 6 +#MaxSessions 10 + +#PubkeyAuthentication yes + +# Expect .ssh/authorized_keys2 to be disregarded by default in future. +#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 + +#AuthorizedPrincipalsFile none + +#AuthorizedKeysCommand none +#AuthorizedKeysCommandUser nobody + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +#HostbasedAuthentication no +# Change to yes if you don't trust ~/.ssh/known_hosts for +# HostbasedAuthentication +#IgnoreUserKnownHosts no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes + +# To disable tunneled clear text passwords, change to no here! +#PasswordAuthentication yes +#PermitEmptyPasswords no + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication no + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes +#GSSAPIStrictAcceptorCheck yes +#GSSAPIKeyExchange no + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM yes + +#AllowAgentForwarding yes +#AllowTcpForwarding yes +#GatewayPorts no +X11Forwarding yes +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PermitTTY yes +PrintMotd no +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +#UsePrivilegeSeparation sandbox +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS no +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 diff --git a/pkg/wg/ask.sh b/pkg/wg/ask.sh index 22411e8..df0bbb9 100755 --- a/pkg/wg/ask.sh +++ b/pkg/wg/ask.sh @@ -12,7 +12,7 @@ cmdline() { [ -f "/var/lib/adlin/wireguard/adlin.token" ] && WGTOKEN=$(cat /var/lib/adlin/wireguard/adlin.token) [ -z "${WGTOKEN}" ] && WGTOKEN=$(cmdline adlin.token) [ -z "${WGTOKEN}" ] && { - echo "You didn't define your token to connect the network. Please run here `join-p0m` and then reboot." + echo "You didn't define your token to connect the network. Please run here \`join-maatma\` and then reboot." exit 1 } [ -f "/var/lib/adlin/wireguard/adlin.conf" ] && WGPRVKEY=$(sed 's/^.*PrivateKey *= *//p;d' /var/lib/adlin/wireguard/adlin.conf) @@ -23,9 +23,9 @@ do exit 1 done echo -n "${WGTOKEN}" > /var/lib/adlin/wireguard/adlin.token -/sbin/ip link add dev wg0 type wireguard -/usr/bin/wg setconf wg0 /var/lib/adlin/wireguard/adlin.conf -/sbin/ip address add dev wg0 $(sed 's/^.*MyIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf) -/sbin/ip link set up dev wg0 -/sbin/ip -6 route del default -/sbin/ip -6 route add default via $(sed 's/^.*GWIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf) pref high +#/sbin/ip link add dev wg0 type wireguard +#/usr/bin/wg setconf wg0 /var/lib/adlin/wireguard/adlin.conf +#/sbin/ip address add dev wg0 $(sed 's/^.*MyIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf) +#/sbin/ip link set up dev wg0 +#/sbin/ip -6 route del default +#/sbin/ip -6 route add default via $(sed 's/^.*GWIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf) pref high diff --git a/token-validator/htdocs/js/adlin-common.js b/token-validator/htdocs/js/adlin-common.js index a6e4f55..f574d44 100644 --- a/token-validator/htdocs/js/adlin-common.js +++ b/token-validator/htdocs/js/adlin-common.js @@ -23,6 +23,14 @@ var tuto_progress = [ 107: { title: "DNSSEC (bonus)", icon: "7", label: "DNSSEC"}, }, { - 200: { title: "HTTP", label: "HTTP"}, + 200: { title: "PONG resolver", icon: "0", label: "PONG srv"}, + 201: { title: "HTTP on IP (bonus)", icon: "1", label: "HTTP IP"}, + 203: { title: "DNS Delegation", icon: "2", label: "DNS"}, + 204: { title: "HTTP on delegated domain", icon: "3", label: "HTTP on NS"}, + 205: { title: "HTTPS on delegated domain", icon: "4", label: "HTTPS on NS"}, + 206: { title: "Matrix", icon: "5", label: "Matrix"}, + 208: { title: "RH access net", icon: "6", label: "RH net"}, + 209: { title: "DG access net", icon: "7", label: "DG net"}, + 210: { title: "CM access net", icon: "8", label: "CM net"}, }, ]; diff --git a/token-validator/htdocs/js/adlin-dashboard.js b/token-validator/htdocs/js/adlin-dashboard.js index 8737bd9..cf2d6ee 100644 --- a/token-validator/htdocs/js/adlin-dashboard.js +++ b/token-validator/htdocs/js/adlin-dashboard.js @@ -109,22 +109,26 @@ angular.module("AdLinApp") .controller("StudentProgressionController", function($scope, $interval, $http, Student, StudentProgression) { $scope.tuto_progress = tuto_progress; var refreshStd = function() { - $scope.student = Student.get({studentId: $scope.onestudent}) - $scope.img = $scope.onestudent == "nemunaire" ? "mercie_d" : $scope.onestudent - $scope.mychallenges = StudentProgression.get({studentId: $scope.onestudent}) - $scope.mychallenges.$promise.then(function(mychallenges) { - angular.forEach(mychallenges, function(ch, chid) { - if (ch.time) { - mychallenges[chid].time = new Date(ch.time); - mychallenges[chid].recent = (Date.now() - mychallenges[chid].time)/1000; - } - }); - }) - $scope.student.$promise.then(function(student) { + var student = Student.get({studentId: $scope.onestudent}) + student.$promise.then(function(stdnt) { + $scope.student = stdnt $http.get("/api/students/" + $scope.student.id + "/ips").then(function(response) { $scope.ips = response.data; }); }) + + var mychallenges = StudentProgression.get({studentId: $scope.onestudent}) + mychallenges.$promise.then(function(mychals) { + angular.forEach(mychals, function(ch, chid) { + if (ch.time) { + mychals[chid].time = new Date(ch.time); + mychals[chid].recent = (Date.now() - mychals[chid].time)/1000; + } + }); + $scope.mychallenges = mychals + }) + + $scope.img = $scope.onestudent == "nemunaire" ? "mercie_d" : $scope.onestudent } $scope.$watch("onestudent", function(onestudent) { refreshStd(); diff --git a/token-validator/main.go b/token-validator/main.go index c2fdefa..a94d373 100644 --- a/token-validator/main.go +++ b/token-validator/main.go @@ -2,6 +2,7 @@ package main import ( "context" + "encoding/base64" "flag" "fmt" "log" @@ -16,7 +17,9 @@ import ( "git.nemunai.re/lectures/adlin/libadlin" ) -var baseURL string = "/" +var ( + baseURL string = "/" +) type ResponseWriterPrefix struct { real http.ResponseWriter @@ -59,6 +62,8 @@ func StripPrefix(prefix string, h http.Handler) http.Handler { } func main() { + var err error + if v, exists := os.LookupEnv("ADLIN_NS_HOST"); exists { ControlSocket = v } @@ -68,6 +73,13 @@ func main() { if v, exists := os.LookupEnv("ADLIN_TSIG_SECRET"); exists { tsigSecret = v } + if v, exists := os.LookupEnv("ADLIN_COLLECTOR_SECRET"); !exists { + log.Fatal("Please define ADLIN_COLLECTOR_SECRET environment variable") + } else if t, err := base64.StdEncoding.DecodeString(v); err != nil { + log.Fatal("Error reading ADLIN_COLLECTOR_SECRET variable:", err) + } else { + adlin.SetCollectorSecret(t) + } var bind = flag.String("bind", ":8081", "Bind port/socket") var dsn = flag.String("dsn", adlin.DSNGenerator(), "DSN to connect to the MySQL server") @@ -82,7 +94,6 @@ func main() { flag.Parse() // Sanitize options - var err error log.Println("Checking paths...") if err = sanitizeStaticOptions(); err != nil { log.Fatal(err) diff --git a/token-validator/wg.go b/token-validator/wg.go index e80544b..aa2fcd9 100644 --- a/token-validator/wg.go +++ b/token-validator/wg.go @@ -17,6 +17,9 @@ import ( ) func init() { + router.GET("/api/collector_info", apiHandler(func(ps httprouter.Params, body []byte) (interface{}, error) { + return "\"" + base64.StdEncoding.EncodeToString(adlin.GetCollectorPublic()) + "\"", nil + })) router.GET("/api/wg.conf", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Content-Type", "text/plain") @@ -149,7 +152,8 @@ PersistentKeepalive = 5 # MyNetwork=%s/%d # GWIPv6=%s # MyLogin=%s -`, base64.StdEncoding.EncodeToString(tinfo.SrvPubKey), "82.64.31.248", tinfo.SrvPort, tinfo.CltIPv6, token.SuffixIP, 64, tinfo.CltIPv6, tinfo.CltRange, tinfo.SrvGW6, student.Login))) +# KeySign=%s +`, base64.StdEncoding.EncodeToString(tinfo.SrvPubKey), "82.64.31.248", tinfo.SrvPort, tinfo.CltIPv6, token.SuffixIP, 64, tinfo.CltIPv6, tinfo.CltRange, tinfo.SrvGW6, student.Login, base64.StdEncoding.EncodeToString(token.GenKeySign())))) } func updateWgTunnel(student *adlin.Student, ps httprouter.Params, body []byte) (interface{}, error) { diff --git a/tuto3.yml b/tuto3.yml index c05a1e6..e666e7b 100644 --- a/tuto3.yml +++ b/tuto3.yml @@ -1,5 +1,5 @@ kernel: - image: linuxkit/kernel:4.19.113 + image: linuxkit/kernel:4.19.121 # cmdline: "console=ttyS0 root=/dev/sda1 root=/dev/sr0 adlin.token=LqCdJDfniA" cmdline: "console=tty0" @@ -40,9 +40,25 @@ onboot: net: /run/netns/router services: - - name: dhcpcd-wks1 + - name: dhcpcd-wks-dg1 image: linuxkit/dhcpcd:v0.8 - hostname: wks1 + hostname: wks-dg1 + net: new + pid: new + ipc: new + uts: new + runtime: + interfaces: + - name: ethwks-dg1 + bindNS: + net: /run/netns/wks-dg1 + uts: /run/utsns/wks-dg1 + binds: + - /var/lib/adlin/wks-dg1resolv.conf:/etc/resolv.conf + + - name: dhcpcd-wks-rh1 + image: linuxkit/dhcpcd:v0.8 + hostname: wks-rh1 net: new pid: new ipc: new @@ -50,55 +66,72 @@ services: runtime: interfaces: - name: eth1 - - name: ethwks1 + - name: ethwks-rh1 bindNS: - net: /run/netns/wks1 - uts: /run/utsns/wks1 + net: /run/netns/wks-rh1 + uts: /run/utsns/wks-rh1 binds: - - /var/lib/adlin/wks1resolv.conf:/etc/resolv.conf + - /var/lib/adlin/wks-rh1resolv.conf:/etc/resolv.conf - - name: dhcpcd-wks2 + - name: dhcpcd-wks-rh2 image: linuxkit/dhcpcd:v0.8 - hostname: wks2 + hostname: wks-rh2 net: new pid: new ipc: new uts: new runtime: interfaces: - - name: ethwks2 + - name: ethwks-rh2 bindNS: - net: /run/netns/wks2 - uts: /run/utsns/wks2 + net: /run/netns/wks-rh2 + uts: /run/utsns/wks-rh2 binds: - - /var/lib/adlin/wks2resolv.conf:/etc/resolv.conf + - /var/lib/adlin/wks-rh2resolv.conf:/etc/resolv.conf - - name: sshd-wks1 + - name: dhcpcd-wks-cm1 + image: linuxkit/dhcpcd:v0.8 + hostname: wks-cm1 + net: new + pid: new + ipc: new + uts: new + runtime: + interfaces: + - name: ethwks-cm1 + bindNS: + net: /run/netns/wks-cm1 + uts: /run/utsns/wks-cm1 + binds: + - /var/lib/adlin/wks-cm1resolv.conf:/etc/resolv.conf + + - name: sshd-wks-dg1 image: linuxkit/sshd:v0.8 - net: /run/netns/wks1 - uts: /run/utsns/wks1 + net: /run/netns/wks-dg1 + uts: /run/utsns/wks-dg1 pid: new ipc: new binds: - /etc/ssh/sshd_config:/etc/ssh/sshd_config - /etc/wpasswd:/etc/passwd - /etc/wshadow:/etc/shadow - - /var/lib/adlin/wks1resolv.conf:/etc/resolv.conf + - /var/lib/adlin/wks-dg1resolv.conf:/etc/resolv.conf - - name: sshd-wks2 + - name: sshd-wks-rh1 image: linuxkit/sshd:v0.8 - net: /run/netns/wks2 - uts: /run/utsns/wks2 + net: /run/netns/wks-rh1 + uts: /run/utsns/wks-rh1 pid: new ipc: new binds: - /etc/ssh/sshd_config:/etc/ssh/sshd_config - /etc/wpasswd:/etc/passwd - /etc/wshadow:/etc/shadow - - /var/lib/adlin/wks2resolv.conf:/etc/resolv.conf + - /var/lib/adlin/wks-rh1resolv.conf:/etc/resolv.conf - name: mainrouter - image: nemunaire/adlin-tuto3:a8593e91cb830dede2ad25a205ef47141a5a3c22 + #image: nemunaire/adlin-tuto3:485bb9556ca3bc33e7fee16edd93c05f35eb1455 + image: nemunaire/router-tuto3:c07718ca23c03ff5033c4042f0cbeca6c26d4e6f net: /run/netns/router pid: new ipc: new @@ -111,10 +144,16 @@ services: - type: cgroup options: ["rw","nosuid","noexec","nodev","relatime"] binds: + - /var/lib/adlin/wrt-etc:/etc + - /etc/rinittab:/etc/inittab - /etc/hosts:/etc/hosts:ro - /etc/dresolv.conf:/etc/resolv.conf + - /etc/rsysctl.conf:/etc/sysctl.d/10-default.conf:ro + - /lib/preinit/20_check_iso:/lib/preinit/20_check_iso + - /lib/preinit/30_failsafe_wait:/lib/preinit/30_failsafe_wait + - /lib/preinit/99_10_failsafe_login:/lib/preinit/99_10_failsafe_login - name: matrix - image: nemunaire/tinydeb:eaa617bf726fb4cadfa22b3947709579e6001212 + image: nemunaire/tinydeb:2ec3c0260da7242df267799dfe08fe2eb0d014b1 net: /run/netns/chat pid: new ipc: new @@ -130,7 +169,7 @@ services: - /etc/hosts:/etc/hosts:ro - /etc/dresolv.conf:/etc/resolv.conf - name: ns-resolv - image: nemunaire/unbound:ed3ccbb5340aefd48c53a97743fdc6edc7011103 + image: nemunaire/unbound:4988e30d81f3b1782e7bc520d2d24123930d72a6 net: /run/netns/ns pid: new ipc: new @@ -138,7 +177,11 @@ services: hostname: resolvsrv capabilities: - all + mounts: + - type: cgroup + options: ["rw","nosuid","noexec","nodev","relatime"] binds: + - /etc/network:/etc/network:ro - /etc/unbound:/etc/unbound:ro - /etc/services:/etc/services:ro - name: ns-auth @@ -177,7 +220,7 @@ services: - LANG=en_US.utf8 - PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/" - PGDATA=/var/lib/postgresql/data - - POSTGRES_PASSWORD=adlin2021 + - POSTGRES_PASSWORD=adlin2022 binds: - /etc/services:/etc/services:ro - /initdb/:/docker-entrypoint-initdb.d/:ro @@ -194,7 +237,7 @@ services: # env: # - MM_USERNAME=mattermost # - MM_DBNAME=mattermost -# - MM_PASSWORD=adlin2021 +# - MM_PASSWORD=adlin2022 # binds: # - /etc/services:/etc/services:ro # - /etc/hosts:/etc/hosts:ro @@ -209,18 +252,18 @@ services: - all command: ["/bin/sh", "-c", "sleep 10; /usr/bin/miniflux"] env: - - DATABASE_URL=postgres://miniflux:adlin2021@db/miniflux?sslmode=disable + - DATABASE_URL=postgres://miniflux:adlin2022@db/miniflux?sslmode=disable - RUN_MIGRATIONS=1 - CREATE_ADMIN=1 - ADMIN_USERNAME=adeline - - ADMIN_PASSWORD=adlin2021 + - ADMIN_PASSWORD=adlin2022 - LISTEN_ADDR=0.0.0.0:8080 binds: - /etc/hosts:/etc/hosts:ro - /etc/dresolv.conf:/etc/resolv.conf - /etc/services:/etc/services:ro - name: web - image: nemunaire/tinydeb:eaa617bf726fb4cadfa22b3947709579e6001212 + image: nemunaire/tinydeb:2ec3c0260da7242df267799dfe08fe2eb0d014b1 net: /run/netns/web pid: new ipc: new @@ -235,17 +278,64 @@ services: binds: - /etc/dresolv.conf:/etc/resolv.conf + # Workstation testers + - name: minichecker-wks-rh2 + image: nemunaire/minichecker:a5d37bb2ebed6df0e586184582763eb0cf727b51 + net: /run/netns/wks-rh2 + pid: new + ipc: new + uts: /run/utsns/wks-rh2 + command: ["/bin/minichecker", "-check-interval", "50s", "-target", "https://adlin.nemunai.re"] + binds: + - /var/lib/adlin/wks-rh2resolv.conf:/etc/resolv.conf + - /var/lib/adlin/wireguard/:/etc/wireguard/:ro + - name: minichecker-wks-dg1 + image: nemunaire/minichecker:a5d37bb2ebed6df0e586184582763eb0cf727b51 + net: /run/netns/wks-dg1 + pid: new + ipc: new + uts: /run/utsns/wks-dg1 + command: ["/bin/minichecker", "-check-interval", "50s", "-target", "https://adlin.nemunai.re"] + binds: + - /etc/hosts-minichecker:/etc/hosts:ro + - /var/lib/adlin/wks-dg1resolv.conf:/etc/resolv.conf + - /var/lib/adlin/wireguard/:/etc/wireguard/:ro + - name: minichecker-wks-cm1 + image: nemunaire/minichecker:a5d37bb2ebed6df0e586184582763eb0cf727b51 + net: /run/netns/wks-cm1 + pid: new + ipc: new + uts: /run/utsns/wks-cm1 + command: ["/bin/minichecker", "-check-interval", "50s", "-target", "https://adlin.nemunai.re"] + binds: + - /etc/hosts-minichecker:/etc/hosts:ro + - /var/lib/adlin/wireguard/:/etc/wireguard/:ro + files: - path: etc/hosts contents: | - 127.0.0.1 localhost - ::1 localhost - 172.23.42.2 ns - 172.23.42.3 ns-auth - 172.23.42.4 db - 172.23.42.5 matrix - 172.23.42.6 news - 172.23.42.7 web + 127.0.0.1 localhost + ::1 localhost + 172.23.42.2 ns + 172.23.42.3 ns-auth + 172.23.42.4 db + 172.23.42.5 matrix + 172.23.42.6 news + 172.23.42.7 web + 82.64.31.248 adlin.nemunai.re + mode: "0444" + + - path: etc/hosts-minichecker + contents: | + 127.0.0.1 localhost + ::1 localhost + 172.23.42.2 ns + 172.23.42.3 ns-auth + 172.23.42.4 db + 172.23.42.5 matrix + 172.23.42.6 news + 172.23.42.7 web + 82.64.31.248 adlin.nemunai.re mode: "0444" - path: etc/sysctl.d/adlin.conf @@ -268,17 +358,17 @@ files: - path: /usr/bin/reset-router-firewall contents: | #!/bin/sh - PS=$(pgrep systemd | head -1) - nsenter -t "${PS}" -a iptables -F - nsenter -t "${PS}" -a iptables -P INPUT ACCEPT - nsenter -t "${PS}" -a iptables -P FORWARD ACCEPT - nsenter -t "${PS}" -a iptables -P OUTPUT ACCEPT - nsenter -t "${PS}" -a iptables -t nat -F + PS=$(pgrep procd | head -1) + nsenter -t "${PS}" -a -- iptables -F + nsenter -t "${PS}" -a -- iptables -P INPUT ACCEPT + nsenter -t "${PS}" -a -- iptables -P FORWARD ACCEPT + nsenter -t "${PS}" -a -- iptables -P OUTPUT ACCEPT + nsenter -t "${PS}" -a -- iptables -t nat -F mode: "0755" - path: /usr/sbin/wg contents: | - nsenter -n/run/netns/router /usr/bin/wg $@ + nsenter -n/run/netns/router -- /usr/bin/wg $@ mode: "0755" - path: /initdb/init-miniflux.sh @@ -286,7 +376,7 @@ files: #!/bin/sh set -e psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL - CREATE USER miniflux WITH PASSWORD 'adlin2021'; + CREATE USER miniflux WITH PASSWORD 'adlin2022'; CREATE DATABASE miniflux; GRANT ALL PRIVILEGES ON DATABASE miniflux TO miniflux; EOSQL @@ -297,14 +387,14 @@ files: - path: /initdb/init-matrix.sql contents: | - CREATE USER matrix WITH PASSWORD 'adlin2021'; + CREATE USER matrix WITH PASSWORD 'adlin2022'; CREATE DATABASE matrix ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0 OWNER matrix; GRANT ALL PRIVILEGES ON DATABASE matrix TO matrix; mode: "0444" - path: /initdb/init-website.sql contents: | - CREATE USER website WITH PASSWORD 'adlin2021'; + CREATE USER website WITH PASSWORD 'adlin2022'; CREATE DATABASE website ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0 OWNER website; GRANT ALL PRIVILEGES ON DATABASE website TO website; mode: "0444" @@ -313,31 +403,31 @@ files: contents: | #!/bin/sh mkdir -p /var/lib/adlin/ - rm -rf /var/lib/adlin/wks1resolv.conf /var/lib/adlin/wks2resolv.conf - touch /var/lib/adlin/wks1resolv.conf /var/lib/adlin/wks2resolv.conf + rm -rf /var/lib/adlin/wks-dg1resolv.conf /var/lib/adlin/wks-rh1resolv.conf /var/lib/adlin/wks-rh2resolv.conf /var/lib/adlin/wks-cm1resolv.conf + touch /var/lib/adlin/wks-dg1resolv.conf /var/lib/adlin/wks-rh1resolv.conf /var/lib/adlin/wks-rh2resolv.conf /var/lib/adlin/wks-cm1resolv.conf mode: "0755" - path: etc/init.d/011-tuto-net contents: | #!/bin/sh mkdir -p /var/lib/adlin/wireguard/ - nsenter -n/run/netns/router /usr/bin/ask.sh + nsenter -n/run/netns/router -- /usr/bin/ask.sh # Network: workstations ip link add ethwks type veth peer name veth-wks - ip link set ethwks up ip link set ethwks netns router - ip netns exec router ip a add 192.168.6.254/24 dev ethwks - grep MyIPv6= /var/lib/adlin/wireguard/adlin.conf > /dev/null && - ip netns exec router ip a add $(sed 's/^.*MyIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf | sed "s#:[^:/]*/.*\$#1::1/96#") dev ethwks + #ip link set ethwks up + #ip netns exec router ip a add 192.168.6.254/24 dev ethwks + #grep MyIPv6= /var/lib/adlin/wireguard/adlin.conf > /dev/null && + # ip netns exec router ip a add $(sed 's/^.*MyIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf | sed "s#:[^:/]*/.*\$#1::1/96#") dev ethwks # Network: servers ip link add ethsrv type veth peer name veth-srv ip link set ethsrv netns router - ip netns exec router ip link set ethsrv up - ip netns exec router ip a add 172.23.42.1/24 dev ethsrv - grep MyIPv6= /var/lib/adlin/wireguard/adlin.conf > /dev/null && - ip netns exec router ip a add $(sed 's/^.*MyIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf | sed "s#:[^:/]*/.*\$#:1/96#") dev ethsrv + #ip netns exec router ip link set ethsrv up + #ip netns exec router ip a add 172.23.42.1/24 dev ethsrv + #grep MyIPv6= /var/lib/adlin/wireguard/adlin.conf > /dev/null && + # ip netns exec router ip a add $(sed 's/^.*MyIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf | sed "s#:[^:/]*/.*\$#:1/96#") dev ethsrv ip netns add ns ip link add vethin-ns type veth peer name veth-ns @@ -426,13 +516,27 @@ files: ip l add brwks type bridge ip link add veth-wks1 type veth peer name ethwks1 + ip link add link ethwks1 name ethwks-dg1 type vlan id 10 ip link add veth-wks2 type veth peer name ethwks2 + ip link add link ethwks2 name ethwks-rh1 type vlan id 11 + ip link add veth-wks3 type veth peer name ethwks3 + ip link add link ethwks3 name ethwks-rh2 type vlan id 11 + ip link add veth-wks4 type veth peer name ethwks4 + ip link add link ethwks4 name ethwks-cm1 type vlan id 12 ip link set veth-wks master brwks ip link set veth-wks1 master brwks ip link set veth-wks2 master brwks + ip link set veth-wks3 master brwks + ip link set veth-wks4 master brwks ip link set veth-wks up ip link set veth-wks1 up ip link set veth-wks2 up + ip link set veth-wks3 up + ip link set veth-wks4 up + ip link set ethwks1 up + ip link set ethwks2 up + ip link set ethwks3 up + ip link set ethwks4 up ip link set brwks up ip l | grep eth2 > /dev/null && { ip link set eth2 up @@ -443,24 +547,119 @@ files: - path: etc/init.d/012-dl-fixes contents: | #!/bin/sh - ip netns exec router wget -O - --header "X-ADLIN-time: $(stat -c %Y /boot)" https://adlin.nemunai.re/fix-vm | sh + ip netns exec router wget -q -O - --header "X-ADLIN-time: $(stat -c %Y /boot)" https://adlin.nemunai.re/fix-vm | sh + mode: "0755" + + - path: etc/init.d/014-default-router-config + contents: | + #!/bin/sh + [ -d /var/lib/adlin/wrt-etc ] || { + mkdir -p /var/lib/adlin/wrt-etc + cp -r /containers/services/mainrouter/lower/etc/* /var/lib/adlin/wrt-etc/ + + # Configured by students + rm -f /var/lib/adlin/wrt-etc/config/firewall + touch /var/lib/adlin/wrt-etc/config/firewall + + # Avoid listening on IPv6 + sed -r -i '/list\s+listen_http\s+\[::\]:80/d;/list\s+listen_https\s+\[::\]:443/d' /var/lib/adlin/wrt-etc/config/uhttpd + + # Configure networking + cat > /var/lib/adlin/wrt-etc/config/network <> /var/lib/adlin/wrt-etc/config/firewall <> /var/lib/adlin/wrt-etc/config/network < /dev/null > /dev/null + nsenter -t $(pgrep procd | head -1) -a -- curl -s -u adeline:adlin2022 -d @- http://172.23.42.6:8080/v1/import < /root/feeds.opml 2> /dev/null > /dev/null exit 0 mode: "0555" @@ -496,15 +714,18 @@ files: source: pkg/debian-tuto3/issue mode: "0444" - - path: /etc/init.d/500-showip.sh + - path: /etc/init.d/900-showip.sh contents: | #!/bin/sh - echo - cat /etc/issue.adlin - echo - nsenter -n/run/netns/router ip -c a show dev wg0 2> /dev/null || nsenter -n/run/netns/router /usr/bin/ask.sh - nsenter -n/run/netns/router ip -c a show dev eth0 - nsenter -n/run/netns/wks1 ip -c a show dev eth1 2> /dev/null || echo "Attachez une seconde carte ethernet à la VM pour pouvoir vous connecter à un poste de travail." + + # Wait wg0 + nsenter -n/run/netns/router -- ip a show dev wg0 2> /dev/null > /dev/null || sleep 1 + nsenter -n/run/netns/router -- ip a show dev wg0 2> /dev/null > /dev/null || sleep 1 + nsenter -n/run/netns/router -- ip a show dev wg0 2> /dev/null > /dev/null || sleep 1 + nsenter -n/run/netns/router -- ip a show dev wg0 2> /dev/null > /dev/null || sleep 1 + nsenter -n/run/netns/router -- ip a show dev wg0 2> /dev/null > /dev/null || sleep 1 + + /usr/bin/welcome exit 0 mode: "0555" @@ -521,13 +742,18 @@ files: - path: /usr/bin/welcome contents: | #!/bin/sh - /etc/init.d/500-showip.sh + echo + cat /etc/issue.adlin + echo + nsenter -n/run/netns/router -- ip -c a show dev wg0 2> /dev/null || nsenter -n/run/netns/router /usr/bin/ask.sh + nsenter -n/run/netns/router -- ip -c a show dev eth0 + nsenter -n/run/netns/wks-rh1 -- ip -c a show dev eth1 2> /dev/null || echo "Attachez une seconde carte ethernet à la VM pour pouvoir vous connecter à un poste de travail." mode: "0755" - path: /usr/sbin/sos-dhcp contents: | #!/bin/sh - nsenter -t $(pgrep dhcpcd) -a dhcpcd + nsenter -t $(pgrep procd) -a -- udhcpc -i eth0 mode: "0755" - path: /usr/sbin/raz-my-dd @@ -535,12 +761,12 @@ files: #!/bin/sh echo -n "Are you sure? Press Enter to continue... " read -s - dd if=/dev/zero of=/dev/sda size=10 bs=4096 + dd if=/dev/zero of=/dev/sda count=10 bs=4096 sync reboot -f mode: "0755" - - path: /usr/sbin/join-p0m + - path: /usr/sbin/join-maatma contents: | #!/bin/sh [ -s "/var/lib/adlin/wireguard/adlin.token" ] && echo "A token is already defined. You'll erase it it you continue." @@ -548,7 +774,8 @@ files: read WGTOKEN mkdir -p /var/lib/adlin/wireguard/ echo $WGTOKEN > /var/lib/adlin/wireguard/adlin.token - echo "Token saved. You need to reboot now." + nsenter -n/run/netns/router /usr/bin/ask.sh && /usr/bin/update-wg-conf && nsenter -t $(pgrep procd) -a -- /etc/init.d/network restart + echo "Token saved. You should reboot now." mode: "0755" - path: /usr/sbin/diagnostic @@ -562,10 +789,10 @@ files: echo -n "Disque dur monté : "; df /var/lib/adlin/ | grep ^/dev/sd > /dev/null && ok || ko echo echo -n "Token Maatma renseigné : "; [ -s "/var/lib/adlin/wireguard/adlin.token" ] && ok -n || ko -n - echo -n " - Tunnel monté : "; nsenter -n/run/netns/router /usr/bin/wg show wg0 > /dev/null 2> /dev/null && ok -n || ko -n - echo -n " - Tunnel établit : "; [ "$(nsenter -n/run/netns/router /usr/bin/wg show wg0 dump | tail -1 | cut -f 6 2> /dev/null)" != "0" ] && ok || ko - echo -n "Ping Gateway Maatma : "; nsenter -n/run/netns/router ping -w 2 -c 1 2a01:e0a:2b:2252::1 > /dev/null 2> /dev/null && ok -n || ko -n - echo -n " - Ping Internet IPv4 : "; nsenter -n/run/netns/router ping -w 2 -c 1 1.1.1.1 > /dev/null 2> /dev/null && ok || ko + echo -n " - Tunnel monté : "; nsenter -n/run/netns/router -- /usr/bin/wg show wg0 > /dev/null 2> /dev/null && ok -n || ko -n + nsenter -n/run/netns/router -- /usr/bin/wg show wg0 > /dev/null 2> /dev/null && echo -n " - Tunnel établi : "; [ "$(nsenter -n/run/netns/router -- /usr/bin/wg show wg0 dump | tail -1 | cut -f 6 2> /dev/null)" != "0" ] && ok || ko + echo -n "Ping Gateway Maatma : "; nsenter -n/run/netns/router -- ping -w 2 -c 1 2a01:e0a:2b:2252::1 > /dev/null 2> /dev/null && ok -n || ko -n + echo -n " - Ping Internet IPv4 : "; nsenter -n/run/netns/router -- ping -w 2 -c 1 1.1.1.1 > /dev/null 2> /dev/null && ok || ko echo echo -n "États serveurs : "; ctr -n services.linuxkit t ls | grep mainrouter | grep RUNNING > /dev/null && ok -n "Routeur" || ko -n "Routeur" @@ -584,13 +811,23 @@ files: echo echo echo -n "États Workstations : " - ctr -n services.linuxkit t ls | grep dhcpcd-wks1 | grep RUNNING > /dev/null && ok -n "WKS-1" || ko -n "WKS-1" + ctr -n services.linuxkit t ls | grep dhcpcd-wks-dg1 | grep RUNNING > /dev/null && ok -n "WKS-DG1" || ko -n "WKS-DG1" echo -n "(" - ctr -n services.linuxkit t ls | grep sshd-wks1 | grep RUNNING > /dev/null && ok -n "SSH" || ko -n "SSH" + ctr -n services.linuxkit t ls | grep sshd-wks-dg1 | grep RUNNING > /dev/null && ok -n "SSH" || ko -n "SSH" + echo -n " " + ctr -n services.linuxkit t ls | grep minichecker-wks-dg1 | grep RUNNING > /dev/null && ok -n "CK" || ko -n "CK" echo -n ") " - ctr -n services.linuxkit t ls | grep dhcpcd-wks2 | grep RUNNING > /dev/null && ok -n "WKS-2" || ko -n "WKS-2" + ctr -n services.linuxkit t ls | grep dhcpcd-wks-rh1 | grep RUNNING > /dev/null && ok -n "WKS-RH1" || ko -n "WKS-RH1" echo -n "(" - ctr -n services.linuxkit t ls | grep sshd-wks2 | grep RUNNING > /dev/null && ok -n "SSH" || ko -n "SSH" + ctr -n services.linuxkit t ls | grep sshd-wks-rh1 | grep RUNNING > /dev/null && ok -n "SSH" || ko -n "SSH" + echo -n ") " + ctr -n services.linuxkit t ls | grep dhcpcd-wks-rh2 | grep RUNNING > /dev/null && ok -n "WKS-RH2" || ko -n "WKS-RH2" + echo -n "(" + ctr -n services.linuxkit t ls | grep minichecker-wks-rh2 | grep RUNNING > /dev/null && ok -n "CK" || ko -n "CK" + echo -n ") " + ctr -n services.linuxkit t ls | grep dhcpcd-wks-cm1 | grep RUNNING > /dev/null && ok -n "WKS-CM1" || ko -n "WKS-CM1" + echo -n "(" + ctr -n services.linuxkit t ls | grep minichecker-wks-cm1 | grep RUNNING > /dev/null && ok -n "CK" || ko -n "CK" echo -n ") " echo echo @@ -630,6 +867,7 @@ files: log-queries: yes log-replies: yes use-syslog: no + logfile: "/var/log/unbound.log" hide-identity: yes hide-version: yes qname-minimisation: yes @@ -648,6 +886,23 @@ files: forward-addr: 2606:4700:4700::1111 mode: "0440" + - path: etc/rinittab + contents: | + ::sysinit:/etc/init.d/rcS S boot + ::shutdown:/etc/init.d/rcS K shutdown + + mode: "0644" + + - path: etc/rshadow + contents: | + root:$1$ChIJgCib$1IYTTG.wKCXqbo1RMEQCc0:18706:0:99999:7::: + daemon:*:0:0:99999:7::: + ftp:*:0:0:99999:7::: + network:*:0:0:99999:7::: + nobody:*:0:0:99999:7::: + dnsmasq:x:0:0:99999:7::: + mode: "0640" + - path: etc/wpasswd contents: | root:x:0:0:root:/root:/bin/bash @@ -676,10 +931,9 @@ files: systemd-bus-proxy:x:106:108:systemd Bus Proxy,,,:/run/systemd:/bin/false mode: "0644" - - path: etc/wshadow contents: | - root:$6$QNuPvO59Xk4UO3le$3P0V2ef6dHlKgO1FHsKcPPgOvL.YeCOPFqfIVTtpYn5eEn3xkgGYeM1RMCQ9l/eTc6rRc.l.WeRe1iJVznVGj/:17968:0:99999:7::: + root:$6$4/xWhDY0JERkg6eg$ZKglx2TQT2ITM525di2aOhda9r9L.kUjYArPTF5pVTzi3/SRe.My4Z5Cg9vabK0ax2kZ.lLPFHA8v7jw.0N/8.:18707:0:99999:7::: daemon:*:17575:0:99999:7::: bin:*:17575:0:99999:7::: sys:*:17575:0:99999:7::: @@ -722,6 +976,85 @@ files: nameserver 2620:fe::fe mode: "0644" + - path: etc/rsysctl.conf + contents: | + # Do not edit, changes to this file will be lost on upgrades + # /etc/sysctl.conf can be used to customize sysctl settings + + kernel.panic=3 + kernel.core_pattern=/tmp/%e.%t.%p.%s.core + fs.suid_dumpable=2 + + fs.protected_hardlinks=1 + fs.protected_symlinks=1 + + net.core.bpf_jit_enable=1 + + net.ipv4.conf.default.arp_ignore=1 + net.ipv4.conf.all.arp_ignore=1 + net.ipv4.icmp_echo_ignore_broadcasts=1 + net.ipv4.icmp_ignore_bogus_error_responses=1 + net.ipv4.igmp_max_memberships=100 + net.ipv4.tcp_fin_timeout=30 + net.ipv4.tcp_keepalive_time=120 + net.ipv4.tcp_syncookies=1 + net.ipv4.tcp_timestamps=1 + net.ipv4.tcp_sack=1 + net.ipv4.tcp_dsack=1 + mode: "0644" + + - path: etc/rpreinit + contents: | + #!/bin/sh + # Copyright (C) 2006-2015 OpenWrt.org + # Copyright (C) 2010 Vertical Communications + + mkdir -p /var/lock + mount -t tmpfs none /var/lock + + unset PREINIT + exec /sbin/procd + mode: "0755" + + - path: lib/preinit/20_check_iso + contents: | + #!/bin/sh + # Copyright (C) 2006-2015 OpenWrt.org + # Copyright (C) 2010 Vertical Communications + + check_for_iso() { + echo > /dev/null || ramoverlay + } + + boot_hook_add preinit_mount_root check_for_iso + mode: "0644" + + - path: lib/preinit/30_failsafe_wait + contents: | + #!/bin/sh + # Copyright (C) 2006-2015 OpenWrt.org + # Copyright (C) 2010 Vertical Communications + mode: "0644" + + - path: lib/preinit/99_10_failsafe_login + contents: | + #!/bin/sh + # Copyright (C) 2006-2015 OpenWrt.org + # Copyright (C) 2010 Vertical Communications + + failsafe_netlogin () { + dropbearkey -t rsa -s 1024 -f /tmp/dropbear_failsafe_host_key + dropbear -r /tmp/dropbear_failsafe_host_key <> /dev/null 2>&1 + } + + failsafe_shell() { + echo > /dev/null || ramoverlay + } + + boot_hook_add failsafe failsafe_netlogin + boot_hook_add failsafe failsafe_shell + mode: "0644" + trust: org: - linuxkit diff --git a/tutorial/nat/netfilter.md b/tutorial/nat/netfilter.md index b1e1ae0..6beecac 100644 --- a/tutorial/nat/netfilter.md +++ b/tutorial/nat/netfilter.md @@ -1,23 +1,30 @@ \newpage -Netfilter -========= +Routage +======= -Le projet `netfilter`[^netfilter] est l'implémentation de pare-feu au sein du -noyau Linux. Il s'agit d'un mécanisme de filtrage des paquets réseau basés sur -des règles, chargées par l'espace utilisateur dans le noyau. On utilise pour -cela les programmes `nft` (du projet `nftables`), ou de manière historique -`iptables`. +Votre entreprise dispose d'un modeste routeur utilisant +[OpenWrt](https://openwrt.org/). Il s'agit d'une petite distribution Linux +mettant à disposition une interface web pour configurer son routeur +facilement[^facilement]. -[^netfilter]: +[^facilement]: Si vous préférez, ce TP existe aussi en utilisant une simple + distribution Debian comme routeur. C'est tout aussi efficace et les mêmes + technologies sont en jeu. Demandez à votre professeur l'ISO si vous êtes + intéressés ! + +Au sein du noyau Linux, le [projet `netfilter`](https://netfilter.org/) est +l'implémentation de pare-feu standard. Il s'agit d'un mécanisme de filtrage des +paquets réseau basés sur des règles, chargées par l'espace utilisateur dans le +noyau. On utilise pour cela les programmes `nft` (du projet `nftables`), ou de +manière historique `iptables`. Les deux projets ont une manière de fonctionner très similaire, mais il est important de ne pas les utiliser en même temps, sous peine de voir apparaître des problèmes incompréhensible à déboguer, plus ou moins aléatoirement. -Réseau fonctionnel ? --------------------- +## Réseau fonctionnel ? Première étape : avez-vous vérifié l'état du réseau sur le routeur ? @@ -35,8 +42,7 @@ que vous devriez obtenir sont : contacter. -Donner accès à Internet ------------------------ +## Donner accès à Internet Votre administrateur système vous assure que le serveur de noms est bien lancé et configuré comme demandé. @@ -59,9 +65,53 @@ Test à passer : ``` +Vous pouvez utiliser, par exemple `tcpdump`, pour comprendre ce qu'il se passe +sur votre routeur : -Exposer un service web sur Internet ------------------------------------ +
+``` + router# tcpdump -i ethsrv + router# tcpdump -i eth0 udp and port 53 +``` +
+ +#### Attention : {-} + +Le serveur DNS résolveur met en cache les problèmes qu'il rencontre. Il vous +faudra sans doute patienter une bonne minute, une fois que vous aurez la bonne +configuration, afin qu'il tente à nouveau de contacter un serveur de noms pour +faire une résolution. C'est un comportement normal. + +Depuis l'ISO en version 3.1, vous pouvez vous connecter sur la machine +hébergeant le résolveur afin de le redémarrer manuellement. + + +## Accéder aux autres serveurs du parc + +Depuis le routeur, vous pouvez vous SSH en utilisant le nom d'hôte attribué aux +machines : + +
+ - `ssh root@news` + - `ssh root@matrix` + - `ssh root@web` +
+ + +Depuis l'extérieur, vous devez utiliser le routeur comme *bastion*. Avec SSH, +utilisez l'option `-J` pour désigner une machine intermédiaire qui servira à +accéder à la machine cible : + +
+``` + 42sh$ ssh -J root@$EXT_ROUTER root@172.23.42.3 +``` +
+ + +## Exposer les services + +### Localement Vous avez compris comment vos machines peuvent accéder à Internet sans avoir pour autant d'IP routable sur Internet. Cependant, si cela répond parfaitement @@ -73,13 +123,16 @@ depuis l'interface externe du routeur. Après configuration, depuis un navigateur sur votre poste, vous devriez pouvoir accéder à :
-* `http://$EXT_ROUTER_IP:80/` : Vitrine +* `http://$EXT_ROUTER_IP:8000/` : Vitrine * `http://$EXT_ROUTER_IP:8080/` : Miniflux -* `http://$EXT_ROUTER_IP:8448/` : Matrix +* `http://$EXT_ROUTER_IP:8008/` : Matrix
+Notez bien qu'il s'agit là seulement d'un test avec l'IPv4 de votre routeur. Il +n'est pas encore demandé de faire cela sur l'IPv6 routable sur Internet. -### Miniflux + +### Utiliser Miniflux Utilisez le nom d'utilisateur `adeline` pour vous connecter à miniflux. N'oubliez pas de changer le mot de passe avant que quelqu'un @@ -88,3 +141,11 @@ d'autre s'en charge à votre place ! Si vos serveurs ont bien accès à Internet, vous pourrez mettre à jour la liste des flux pré-enregistrés dans miniflux, afin de faire un peu de veille ! + + +### On passe sur Internet ? (bonus) + +Si jusque là, tout se passe à merveille pour vous (c'est ce que je vous +souhaite !), vous pouvez maintenant rediriger le port 80 et 443 arrivant sur +l'IPv6 de votre routeur, vers ceux du serveur web. Sur lequel nous allons +installer un reverse-proxy... diff --git a/tutorial/nat/topologie.png b/tutorial/nat/topologie.png index 3a3a1e4..e094b97 100644 Binary files a/tutorial/nat/topologie.png and b/tutorial/nat/topologie.png differ diff --git a/tutorial/nat/tutorial.md b/tutorial/nat/tutorial.md index a3fd1e9..00dd9d3 100644 --- a/tutorial/nat/tutorial.md +++ b/tutorial/nat/tutorial.md @@ -3,14 +3,14 @@ title: Administration Linux avancée -- TP n^o^ 3 subtitle: author: Pierre-Olivier *nemunaire* [Mercier]{.smallcaps} institute: EPITA -date: Lundi 30 mars 2020 +date: Lundi 22 mars 2021 abstract: | Durant ce troisième TP, nous allons faire un peu plus de réseau ! \vspace{1em} Tous les éléments de ce TP (exercices et projet) sont à rendre à - au plus tard le dimanche 12 avril 2019 à 23 + au plus tard le dimanche 11 avril 2021 à 23 h 42. Consultez la dernière section de chaque partie pour plus d'information sur les éléments à rendre. diff --git a/tutorial/nat/what.md b/tutorial/nat/what.md index 02aeb3e..995932d 100644 --- a/tutorial/nat/what.md +++ b/tutorial/nat/what.md @@ -7,24 +7,32 @@ Présentation du système d'information ------------------------------------- Le système d'information que vous allez avoir à gérer aujourd'hui est de taille -moyenne : vous aurez en votre possession un serveur DNS résolveur, un serveur -DNS autoritaire, un serveur de base de données ainsi que plusieurs serveurs web -(servant respectivement votre vitrine, [Miniflux](https://miniflux.app/), ainsi -que [Matrix](https://matrix.org/)). +moyenne. Vous aurez en votre possession : + + - un serveur DNS résolveur, + - un serveur DNS faisant autorité, + - un serveur de base de données, + - plusieurs serveurs web (servant respectivement votre vitrine, +[Miniflux](https://miniflux.app/), ainsi que [Matrix](https://matrix.org/)), + - de nombreux postes de travail. Vous êtes l'administrateur réseau de l'entreprise et l'on vous demande de connecter tous ces services **correctement**. +Voici un schéma de l'infrastructure complète dont vous allez disposer en +démarrant l'ISO. + +![Architecture réseau à produire](topologie.png "Topologie") + L'image ISO que vous avez récupérée met à votre disposition tout ce système d'information, déjà en partie configuré pour sa partie logicielle, il ne reste plus qu'à éditer la configuration du routeur. -![Architecture réseau à produire](topologie.png "Topologie") - -Attention, contrairement au précédent TP, tout se fait en direct, il n'y a -aucune sauvegarde effectuée : à chaque redémarrage de la machine virtuelle, -vous retomberez dans l'état initial : seuls quelques éléments comme le token de -votre tunnel et le contenu de la base de données. +Attention, contrairement au précédent TP, la majorité des modifications que +vous allez effectuer ne seront pas persistantes d'un reboot à l'autre. À chaque +redémarrage de la machine virtuelle, vous retomberez dans un état initial. +Seuls quelques éléments comme le token de votre tunnel, la configuration du +routeur et le contenu de la base de données persistent. Accéder à la machine virtuelle ------------------------------ @@ -33,7 +41,7 @@ Une fois la machine virtuelle démarrée, vous devriez voir apparaître l'IP qu' obtenue la machine sur votre réseau : ``` - You didn't define your token to connect the network. Please run here `join-p0m` and then reboot. + You didn't define your token to connect the network. Please run here `join-maatma` and then reboot. 4: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 42:2c:63:f1:5a:49 brd ff:ff:ff:ff:ff:ff inet 10.42.23.211/24 brd 10.42.23.255 scope global eth0 @@ -50,15 +58,11 @@ Une ligne de commande est disponible au sein de la machine virtuelle à des fins de débogage, si nécessaire. Vous ne devriez normalement pas avoir à interagir avec celle-ci. -Si vous assignez deux cartes réseau à la machine virtuelle, vous devriez voir -apparaître l'IP de la carte `eth1` en dessous. Il s'agit d'une interface de -station de travail. - ### Tunnel Maatma Pour retrouver votre tunnel sur Internet, vous devez, dans la console de la -machine virtuelle, utiliser la commande `join-p0m`. +machine virtuelle, utiliser la commande `join-maatma`. Vous pouvez aussi écrire directement dans le fichier persistant : @@ -68,13 +72,21 @@ Vous pouvez aussi écrire directement dans le fichier persistant : ``` +Une fois le token renseigné, vous devez redémarrer la machine afin qu'il soit +pris en compte. + + ### Connexions SSH Vous pouvez vous connecter en utilisant le compte `root` et le mot de passe -`adlin2021`. +`adlin2022`. Comme au précédent TP, si vous disposez d'une ou plusieurs [clefs +SSH enregistrées au CRI](https://cri.epita.fr/users/nemunaire/ssh-keys/), +celles-ci sont automatiquement ajoutées aux différents serveurs. Cependant, +seuls les clefs RSA et DSA sont utilisables pour se connecter sur le routeur, +le serveur SSH ne gère pas les courbes éliptiques. -Notez que vous n'avez pas accès à la machine hébergeant la base de données, ni -à celle du résolveur DNS. +Notez que vous n'avez pas accès à la machine hébergeant la base de données, le +lecteur de flux RSS, ni à celle du résolveur DNS. Objectif du TP @@ -89,3 +101,53 @@ s'assurer que ce soit également le cas des stations de travail). Étant donné le caractère éphémère de vos actions, la réalisation d'un *Playbook* Ansible semble plutôt adaptée ! + + +Au secours ça ne marche pas ! +----------------------------- + +Pas de panique ! + +Quelques commandes sont à votre disposition dans le shell de la machine +virtuelle afin de vérifier que tout fonctionne correctement. + + +### Monitoring + +Utilisez la commande `diagnostic` afin d'avoir une vue d'ensemble des éventuel +problèmes. + +Tout est vert ? Toutes les machines sont opérationnelles ! + +Une ou plusieurs machines sont rouges ? il y a effectivement un problème avec +les machines concernées. Tentez de redémarrer une fois. + +Si le problème persiste, vous pouvez formater votre disque en utilisant la +commande `raz-my-dd`. Ce qui vous permettra de retrouver la configuration +d'origine. + +Pour les plus téméraires, les journaux des machines sont regroupés dans +`/var/log` accessible uniquement dans la console de la machine virtuelle. + + +### Retrouver mes IP + +Vous ne pouvez pas simplement taper `ip a` dans le terminal de votre machine +virtuelle. Utilisez plutôt la commande `welcome` qui affichera à nouveau le +message d'accueil avec les différentes IP associées à vos machines. + + +### Rejoindre Maatma + +Utilisez la commande `join-maatma` dans la console de la machine virtuelle, +puis redémarrez la machine. + +Vous pouvez aussi passer par l'interface de votre routeur pour ajouter une +interface 'Wireguard VPN'. Utilisez les informations contenues sur la page +[Tunnels de Maatma](https://adlin.nemunai.re/maatma/tunnels) pour remplir les +différents champs. + + +### `join-maatma` retourne une erreur 400 + +Vérifiez votre token, il n'est pas valide. diff --git a/tutorial/nat/wks.md b/tutorial/nat/wks.md index 9a5a01f..6407054 100644 --- a/tutorial/nat/wks.md +++ b/tutorial/nat/wks.md @@ -24,13 +24,8 @@ N'ayant pas, pour le moment, d'IPv6 sur votre réseau ; vous devez mettre en place un serveur DHCP sur votre réseau afin que vos collaborateurs puissent utiliser facilement le réseau. -Configurez un serveur DHCP, tel quel `isc-dhcp-server` ou `udhcpd` afin de -distribuer des IP correspondant au plan d'adressage. N'oubliez pas de définir -le chemin permettant de sortir sur Internet ainsi que d'utiliser le résolveur -de noms de domaine local. - Une fois configuré, vous pouvez tenter de vous connecter aux services web (vous -devriez avoir `wget` sur la station de travail accessible). +devriez avoir `wget` sur les stations de travail accessibles). Zone démilitarisée et filtrage