Compare commits
21 Commits
a52bf0e52d
...
9ed5cea6e8
Author | SHA1 | Date | |
---|---|---|---|
9ed5cea6e8 | |||
e6a4ffc2ed | |||
8d8df75b6b | |||
ff2a68332b | |||
f81dd3448c | |||
2bb1da63d6 | |||
3e3a0e9e37 | |||
ae3b2e6f3b | |||
5d8bcd55ce | |||
c20ed6630b | |||
a4aadc401a | |||
c889cb4283 | |||
2baa88a7aa | |||
6b81aebc71 | |||
12c74ebbb3 | |||
5500712d60 | |||
bb03770b55 | |||
656e16083d | |||
e6d71ee7f5 | |||
31f871ba67 | |||
c7a1812c9f |
26
Makefile
26
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 $<
|
||||
|
@ -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)
|
||||
}
|
||||
|
47
checker/checks.go
Normal file
47
checker/checks.go
Normal file
@ -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,
|
||||
},
|
||||
}
|
19
go.mod
Normal file
19
go.mod
Normal file
@ -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
|
||||
)
|
440
go.sum
Normal file
440
go.sum
Normal file
@ -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=
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
23
pkg/minichecker/Dockerfile
Normal file
23
pkg/minichecker/Dockerfile
Normal file
@ -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 <nemunaire@nemunai.re>
|
||||
|
||||
COPY --from=gobuild /go/src/minichecker/minichecker /bin/minichecker
|
||||
|
||||
RUN mkdir /etc/wireguard && touch /etc/wireguard/.wireguard
|
||||
|
||||
ENTRYPOINT ["/bin/minichecker"]
|
2
pkg/minichecker/build.yml
Normal file
2
pkg/minichecker/build.yml
Normal file
@ -0,0 +1,2 @@
|
||||
image: minichecker
|
||||
network: true
|
12
pkg/minichecker/cmd/adlin.conf
Normal file
12
pkg/minichecker/cmd/adlin.conf
Normal file
@ -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==
|
1
pkg/minichecker/cmd/adlin.token
Normal file
1
pkg/minichecker/cmd/adlin.token
Normal file
@ -0,0 +1 @@
|
||||
QMzkCN3PPg
|
169
pkg/minichecker/cmd/checker.go
Normal file
169
pkg/minichecker/cmd/checker.go
Normal file
@ -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
|
||||
}
|
83
pkg/minichecker/cmd/encode.go
Normal file
83
pkg/minichecker/cmd/encode.go
Normal file
@ -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
|
||||
}
|
1
pkg/minichecker/cmd/go.mod
Normal file
1
pkg/minichecker/cmd/go.mod
Normal file
@ -0,0 +1 @@
|
||||
module example.com/mod
|
152
pkg/minichecker/cmd/main.go
Normal file
152
pkg/minichecker/cmd/main.go
Normal file
@ -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
|
||||
}
|
||||
}
|
409
pkg/minichecker/cmd/wg.go
Normal file
409
pkg/minichecker/cmd/wg.go
Normal file
@ -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
|
||||
}
|
14
pkg/router-tuto3/Dockerfile
Normal file
14
pkg/router-tuto3/Dockerfile
Normal file
@ -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
|
2
pkg/router-tuto3/build.yml
Normal file
2
pkg/router-tuto3/build.yml
Normal file
@ -0,0 +1,2 @@
|
||||
image: router-tuto3
|
||||
network: true
|
@ -1,15 +1,17 @@
|
||||
FROM alpine
|
||||
MAINTAINER Pierre-Olivier Mercier <nemunaire@nemunai.re>
|
||||
|
||||
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"]}'
|
||||
|
104
pkg/unbound/sshd_config
Normal file
104
pkg/unbound/sshd_config
Normal file
@ -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
|
@ -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
|
||||
|
@ -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"},
|
||||
},
|
||||
];
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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) {
|
||||
|
537
tuto3.yml
537
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 <<EOF
|
||||
|
||||
config interface 'loopback'
|
||||
option ifname 'lo'
|
||||
option proto 'static'
|
||||
option ipaddr '127.0.0.1'
|
||||
option netmask '255.0.0.0'
|
||||
|
||||
config interface 'wan'
|
||||
option ifname 'eth0'
|
||||
option proto 'dhcp'
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
[ -e /var/lib/adlin/wrt-config ] && {
|
||||
mv /var/lib/adlin/wrt-config/* /var/lib/adlin/wrt-etc/config/
|
||||
rmdir /var/lib/adlin/wrt-config
|
||||
}
|
||||
[ -f /var/lib/adlin/wrt-firewall.user ] && mv /var/lib/adlin/wrt-firewall.user /var/lib/adlin/wrt-etc/firewall.user
|
||||
[ -f /var/lib/adlin/wrt-sysctl.conf ] && mv /var/lib/adlin/wrt-sysctl.conf /var/lib/adlin/wrt-etc/sysctl.conf
|
||||
|
||||
# Ensure custom rules are applied
|
||||
grep -q /etc/firewall.user /var/lib/adlin/wrt-etc/config/firewall || cat >> /var/lib/adlin/wrt-etc/config/firewall <<EOF
|
||||
config include
|
||||
option path /etc/firewall.user
|
||||
EOF
|
||||
|
||||
[ -f /var/lib/adlin/wireguard/adlin.conf ] && /usr/bin/update-wg-conf
|
||||
mode: "0755"
|
||||
|
||||
- path: usr/bin/update-wg-conf
|
||||
contents: |
|
||||
#!/bin/sh
|
||||
TUNPVKEY=$(sed 's/^.*PrivateKey = //p;d' /var/lib/adlin/wireguard/adlin.conf)
|
||||
TUNIP=$(sed 's/^.*MyIPv6=//p;d' /var/lib/adlin/wireguard/adlin.conf)
|
||||
SRVIP=$(echo "${TUNIP}" | sed "s#:[^:/]*/.*\$#:1/96#")
|
||||
WKSIP=$(echo "${TUNIP}" | sed "s#:[^:/]*/.*\$#1::1/96#")
|
||||
|
||||
grep -q wireguard /var/lib/adlin/wrt-etc/config/network && {
|
||||
sed -i -r "s#list addresses '[^']+'#list addresses '${TUNIP}'#;s#option private_key '[^']+'#option private_key '${TUNPVKEY}'#;" /var/lib/adlin/wrt-etc/config/network
|
||||
}
|
||||
|
||||
grep -q wireguard /var/lib/adlin/wrt-etc/config/network || cat >> /var/lib/adlin/wrt-etc/config/network <<EOF
|
||||
config interface 'wg0'
|
||||
option proto 'wireguard'
|
||||
option force_link '1'
|
||||
list addresses '${TUNIP}'
|
||||
option private_key '${TUNPVKEY}'
|
||||
|
||||
config wireguard_wg0
|
||||
option public_key 'uSpqyYovvP4OG6wDxZ0Qkq45MfyK58PMUuPaLesY8FI='
|
||||
option description 'maatma'
|
||||
option persistent_keepalive '5'
|
||||
list allowed_ips '::/0'
|
||||
option endpoint_host '82.64.31.248'
|
||||
option endpoint_port '42912'
|
||||
|
||||
config interface 'srv'
|
||||
option ifname 'ethsrv'
|
||||
option proto 'static'
|
||||
option netmask '255.255.255.0'
|
||||
option ipaddr '172.23.42.1'
|
||||
list ip6addr '${SRVIP}'
|
||||
|
||||
config route6
|
||||
option target '::/0'
|
||||
option gateway '2a01:e0a:2b:2252::1'
|
||||
option interface 'wg0'
|
||||
|
||||
EOF
|
||||
mode: "0755"
|
||||
|
||||
- path: etc/init.d/014-get-ssh-keys
|
||||
contents: |
|
||||
#!/bin/sh
|
||||
# Retrieve ssh keys
|
||||
[ -f /var/lib/adlin/authorized_keys ] || nsenter -n/run/netns/router -- /usr/bin/wget -O /var/lib/adlin/authorized_keys https://cri.epita.fr/$(sed 's/^.*MyLogin=//p;d' /var/lib/adlin/wireguard/adlin.conf).keys
|
||||
mode: "0755"
|
||||
|
||||
# - path: etc/init.d/021-correction
|
||||
# contents: |
|
||||
# #!/bin/sh
|
||||
# PS=$(pgrep systemd | head -1)
|
||||
# nsenter -t "${PS}" -a sysctl -w net.ipv4.ip_forward=1
|
||||
# nsenter -t "${PS}" -a sysctl -w net.ipv6.conf.all.forwarding=1
|
||||
# nsenter -t "${PS}" -a sysctl -w net.ipv4.conf.ethsrv.route_localnet=1
|
||||
# nsenter -t "${PS}" -a iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
# nsenter -t "${PS}" -a iptables -t nat -A POSTROUTING -o ethsrv -m addrtype --src-type LOCAL -j MASQUERADE
|
||||
# nsenter -t "${PS}" -a iptables -t nat -A PREROUTING -p tcp --dport 8052 -j DNAT --to 172.23.42.9
|
||||
# nsenter -t "${PS}" -a iptables -t nat -A OUTPUT -o lo -p tcp -m tcp --dport 8052 -j DNAT --to-destination 172.23.42.9
|
||||
# nsenter -t "${PS}" -a iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to 172.23.42.6
|
||||
# nsenter -t "${PS}" -a iptables -t nat -A OUTPUT -o lo -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.23.42.6
|
||||
# nsenter -t "${PS}" -a ip link set ethwks up
|
||||
# cat <<EOF | nsenter -t "${PS}" -a tee /etc/udhcpd.conf
|
||||
# PS=$(pgrep procd | head -1)
|
||||
# nsenter -t "${PS}" -a -- sysctl -w net.ipv4.ip_forward=1
|
||||
# nsenter -t "${PS}" -a -- sysctl -w net.ipv6.conf.all.forwarding=1
|
||||
# nsenter -t "${PS}" -a -- sysctl -w net.ipv4.conf.ethsrv.route_localnet=1
|
||||
# nsenter -t "${PS}" -a -- iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
# nsenter -t "${PS}" -a -- iptables -t nat -A POSTROUTING -o ethsrv -m addrtype --src-type LOCAL -j MASQUERADE
|
||||
# nsenter -t "${PS}" -a -- iptables -t nat -A PREROUTING -p tcp --dport 8052 -j DNAT --to 172.23.42.9
|
||||
# nsenter -t "${PS}" -a -- iptables -t nat -A OUTPUT -o lo -p tcp -m tcp --dport 8052 -j DNAT --to-destination 172.23.42.9
|
||||
# nsenter -t "${PS}" -a -- iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to 172.23.42.6
|
||||
# nsenter -t "${PS}" -a -- iptables -t nat -A OUTPUT -o lo -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.23.42.6
|
||||
# nsenter -t "${PS}" -a -- ip link set ethwks up
|
||||
# cat <<EOF | nsenter -t "${PS}" -a -- tee /etc/udhcpd.conf
|
||||
# start 192.168.6.50
|
||||
# end 192.168.6.200
|
||||
# interface ethwks
|
||||
@ -471,24 +670,43 @@ files:
|
||||
# EOF
|
||||
# mode: "0755"
|
||||
|
||||
- path: /etc/init.d/999-rw-passwd.sh
|
||||
- path: /etc/init.d/800-rw-passwd.sh
|
||||
contents: |
|
||||
#!/bin/sh
|
||||
sed -ri '/^root/s@^.*$@root:$6$QNuPvO59Xk4UO3le$3P0V2ef6dHlKgO1FHsKcPPgOvL.YeCOPFqfIVTtpYn5eEn3xkgGYeM1RMCQ9l/eTc6rRc.l.WeRe1iJVznVGj/:17968:0:99999:7:::@' /containers/services/mainrouter/rootfs/etc/shadow
|
||||
cp /etc/services /containers/services/mainrouter/rootfs/etc/services
|
||||
sed -ri '/^root/s@^.*$@root:$6$QNuPvO59Xk4UO3le$3P0V2ef6dHlKgO1FHsKcPPgOvL.YeCOPFqfIVTtpYn5eEn3xkgGYeM1RMCQ9l/eTc6rRc.l.WeRe1iJVznVGj/:17968:0:99999:7:::@' /containers/services/matrix/rootfs/etc/shadow
|
||||
cp /etc/services /containers/services/matrix/rootfs/etc/services
|
||||
sed -ri '/^root/s@^.*$@root:$6$QNuPvO59Xk4UO3le$3P0V2ef6dHlKgO1FHsKcPPgOvL.YeCOPFqfIVTtpYn5eEn3xkgGYeM1RMCQ9l/eTc6rRc.l.WeRe1iJVznVGj/:17968:0:99999:7:::@' /containers/services/ns-auth/rootfs/etc/shadow
|
||||
cp /etc/services /containers/services/web/rootfs/etc/services
|
||||
sed -ri '/^root/s@^.*$@root:$6$QNuPvO59Xk4UO3le$3P0V2ef6dHlKgO1FHsKcPPgOvL.YeCOPFqfIVTtpYn5eEn3xkgGYeM1RMCQ9l/eTc6rRc.l.WeRe1iJVznVGj/:17968:0:99999:7:::@' /containers/services/web/rootfs/etc/shadow
|
||||
sed -ri '/^root/s@^root:x:.*$@root:$1$ChIJgCib$1IYTTG.wKCXqbo1RMEQCc0:18706:0:99999:7:::@' /var/lib/adlin/wrt-etc/shadow
|
||||
mkdir -p /var/lib/adlin/wrt-etc/dropbear/
|
||||
[ -f /var/lib/adlin/authorized_keys ] && ! [ -f /var/lib/adlin/wrt-etc/dropbear/authorized_keys ] && cp /var/lib/adlin/authorized_keys /var/lib/adlin/wrt-etc/dropbear/authorized_keys
|
||||
|
||||
for svc in sshd-wks-rh1 sshd-wks-dg1
|
||||
do
|
||||
mkdir -p /containers/services/${svc}/rootfs/root/.ssh
|
||||
[ -f /var/lib/adlin/authorized_keys ] && cp /var/lib/adlin/authorized_keys /containers/services/${svc}/rootfs/root/.ssh/authorized_keys
|
||||
done
|
||||
|
||||
for svc in matrix ns-auth ns-resolv web
|
||||
do
|
||||
sed -ri '/^root/s@^.*$@root:$6$4/xWhDY0JERkg6eg$ZKglx2TQT2ITM525di2aOhda9r9L.kUjYArPTF5pVTzi3/SRe.My4Z5Cg9vabK0ax2kZ.lLPFHA8v7jw.0N/8.:18707:0:99999:7:::@' /containers/services/${svc}/rootfs/etc/shadow
|
||||
cp /etc/services /containers/services/${svc}/rootfs/etc/services
|
||||
mkdir -p /containers/services/${svc}/rootfs/root/.ssh
|
||||
[ -f /var/lib/adlin/authorized_keys ] && cp /var/lib/adlin/authorized_keys /containers/services/${svc}/rootfs/root/.ssh/authorized_keys
|
||||
nsenter -t $(ctr -n services.linuxkit t ls | grep ${svc} | awk '{ print $2 }') -a ssh-keygen -A
|
||||
done
|
||||
|
||||
exit 0
|
||||
mode: "0555"
|
||||
|
||||
- path: /etc/init.d/850-later-use.sh
|
||||
contents: |
|
||||
#!/bin/sh
|
||||
|
||||
# This file is currently not used and is reserved for future use.
|
||||
mode: "0755"
|
||||
|
||||
- path: /etc/init.d/999-import-feeds.sh
|
||||
contents: |
|
||||
#!/bin/sh
|
||||
sleep 20
|
||||
nsenter -t $(pgrep systemd | head -1) -a curl -s -u adeline:adlin2021 -d @- http://172.23.42.6:8080/v1/import < /root/feeds.opml 2> /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
|
||||
|
@ -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]: <https://netfilter.org/>
|
||||
[^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 :
|
||||
```
|
||||
</div>
|
||||
|
||||
Vous pouvez utiliser, par exemple `tcpdump`, pour comprendre ce qu'il se passe
|
||||
sur votre routeur :
|
||||
|
||||
Exposer un service web sur Internet
|
||||
-----------------------------------
|
||||
<div lang="en-US">
|
||||
```
|
||||
router# tcpdump -i ethsrv
|
||||
router# tcpdump -i eth0 udp and port 53
|
||||
```
|
||||
</div>
|
||||
|
||||
#### 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 :
|
||||
|
||||
<div lang="en-US">
|
||||
- `ssh root@news`
|
||||
- `ssh root@matrix`
|
||||
- `ssh root@web`
|
||||
</div>
|
||||
|
||||
|
||||
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 :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh$ ssh -J root@$EXT_ROUTER root@172.23.42.3
|
||||
```
|
||||
</div>
|
||||
|
||||
|
||||
## 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 à :
|
||||
|
||||
<div lang="en-US">
|
||||
* `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
|
||||
</div>
|
||||
|
||||
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...
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 118 KiB |
@ -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 à
|
||||
<adlin@nemunai.re> au plus tard le dimanche 12 avril 2019 à 23
|
||||
<adlin@nemunai.re> 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.
|
||||
|
||||
|
@ -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: <BROADCAST,MULTICAST,UP,LOWER_UP> 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 :
|
||||
```
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user