From 7187a7d187b37800d8f390acac4d95eb22365265 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Sat, 30 Apr 2022 02:41:12 +0200 Subject: [PATCH] Introduce overrideID option to allow multiple tunnels in parellel --- libadlin/db.go | 1 + libadlin/tunnel.go | 43 ++++++++++++++++++++------------------- token-validator/check.go | 2 +- token-validator/domain.go | 4 ++-- token-validator/ip.go | 2 +- token-validator/wg.go | 10 ++++----- 6 files changed, 32 insertions(+), 30 deletions(-) diff --git a/libadlin/db.go b/libadlin/db.go index cfa149b..edfd639 100644 --- a/libadlin/db.go +++ b/libadlin/db.go @@ -141,6 +141,7 @@ CREATE TABLE IF NOT EXISTS student_tunnel_tokens( time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, pubkey BLOB(50) DEFAULT NULL, suffixip INTEGER NOT NULL, + idoverride INTEGER NOT NULL DEFAULT 0, version INTEGER NOT NULL, FOREIGN KEY(id_student) REFERENCES students(id_student) ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; diff --git a/libadlin/tunnel.go b/libadlin/tunnel.go index 7cbabe2..1f3805b 100644 --- a/libadlin/tunnel.go +++ b/libadlin/tunnel.go @@ -28,13 +28,13 @@ 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)) +func StudentIP(idstd int64, overrideid int) net.IP { + return net.ParseIP(fmt.Sprintf("2a01:e0a:2b:2252:%x%x::", overrideid, idstd)) } -func StudentNet(idstd int64) *net.IPNet { +func StudentNet(idstd int64, overrideid int) *net.IPNet { return &net.IPNet{ - IP: StudentIP(idstd), + IP: StudentIP(idstd, overrideid), Mask: net.CIDRMask(StdNetmask, 128), } } @@ -113,12 +113,13 @@ func readWgDump() (wgd map[string]*WGDump, err error) { } type TunnelToken struct { - token []byte - TokenText string - IdStudent int64 - PubKey []byte - Time time.Time - SuffixIP int + token []byte + TokenText string + IdStudent int64 + PubKey []byte + Time time.Time + SuffixIP int + OverrideID int // Version stores the TP number where the token is used Version int Dump *WGDump @@ -126,14 +127,14 @@ type TunnelToken struct { func (tt *TunnelToken) GetStudentIP() string { if tt.SuffixIP == 0 { - return fmt.Sprintf("%s%x", StudentIP(tt.IdStudent).String(), 1) + return fmt.Sprintf("%s%x", StudentIP(tt.IdStudent, tt.OverrideID).String(), 1) } else { - return fmt.Sprintf("%s%x", StudentIP(tt.IdStudent).String(), tt.SuffixIP) + return fmt.Sprintf("%s%x", StudentIP(tt.IdStudent, tt.OverrideID).String(), tt.SuffixIP) } } func (tt *TunnelToken) GetServerIP(suffix int) string { - return fmt.Sprintf("%s%x", StudentIP(tt.IdStudent).String(), suffix) + return fmt.Sprintf("%s%x", StudentIP(tt.IdStudent, tt.OverrideID).String(), suffix) } func (tt *TunnelToken) GenKeySign() []byte { @@ -151,7 +152,7 @@ func TokenFromText(token string) []byte { func 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=? ORDER BY time DESC", token).Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.Version) + err = DBQueryRow("SELECT token, token_text, id_student, pubkey, time, suffixip, idoverride, version FROM student_tunnel_tokens WHERE token=? ORDER BY time DESC", token).Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.OverrideID, &t.Version) if err == nil && t.PubKey != nil { if wgd, errr := readWgDump(); errr == nil { if v, ok := wgd[base64.StdEncoding.EncodeToString(t.PubKey)]; ok { @@ -178,7 +179,7 @@ func (student *Student) NewTunnelToken(suffixip int) (t *TunnelToken, err error) } func (student *Student) GetTunnelTokens() (ts []*TunnelToken, err error) { - if rows, errr := DBQuery("SELECT token, token_text, id_student, pubkey, time, suffixip, version FROM student_tunnel_tokens WHERE id_student = ? ORDER BY time DESC", student.Id); errr != nil { + if rows, errr := DBQuery("SELECT token, token_text, id_student, pubkey, time, suffixip, idoverride, version FROM student_tunnel_tokens WHERE id_student = ? ORDER BY time DESC", student.Id); errr != nil { return nil, errr } else if wgd, errr := readWgDump(); errr != nil { return nil, errr @@ -187,7 +188,7 @@ func (student *Student) GetTunnelTokens() (ts []*TunnelToken, err error) { for rows.Next() { t := &TunnelToken{} - if err = rows.Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.Version); err != nil { + if err = rows.Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.OverrideID, &t.Version); err != nil { return } if t.PubKey != nil { @@ -206,7 +207,7 @@ func (student *Student) GetTunnelTokens() (ts []*TunnelToken, err error) { } func (student *Student) GetActivesTunnels() (ts []*TunnelToken, err error) { - if rows, errr := DBQuery("SELECT token, token_text, id_student, pubkey, time, suffixip, version FROM student_tunnel_tokens WHERE id_student = ? ORDER BY time DESC", student.Id); errr != nil { + if rows, errr := DBQuery("SELECT token, token_text, id_student, pubkey, time, suffixip, idoverride, version FROM student_tunnel_tokens WHERE id_student = ? ORDER BY time DESC", student.Id); errr != nil { return nil, errr } else if wgd, errr := readWgDump(); errr != nil { return nil, errr @@ -215,7 +216,7 @@ func (student *Student) GetActivesTunnels() (ts []*TunnelToken, err error) { for rows.Next() { t := &TunnelToken{} - if err = rows.Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.Version); err != nil { + if err = rows.Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.OverrideID, &t.Version); err != nil { return } if t.PubKey != nil { @@ -259,7 +260,7 @@ func (student *Student) GetActivesTunnelsPubKey() (ts []ed25519.PublicKey, err e 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) + err = DBQueryRow("SELECT token, token_text, id_student, pubkey, time, suffixip, idoverride, 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.OverrideID, &t.Version) if err == nil && t.PubKey != nil { if wgd, errr := readWgDump(); errr == nil { if v, ok := wgd[base64.StdEncoding.EncodeToString(t.PubKey)]; ok { @@ -296,14 +297,14 @@ func (t *TunnelToken) Delete() (int64, error) { } func GetStudentsTunnels() (ts []*TunnelToken, err error) { - if rows, errr := DBQuery("SELECT T.token, T.token_text, T.id_student, T.pubkey, T.time, T.suffixip, T.version FROM student_tunnel_tokens T INNER JOIN (SELECT B.id_student, MAX(B.time) AS time FROM student_tunnel_tokens B WHERE B.pubkey IS NOT NULL GROUP BY id_student) L ON T.id_student = L.id_student AND T.time = L.time"); errr != nil { + if rows, errr := DBQuery("SELECT T.token, T.token_text, T.id_student, T.pubkey, T.time, T.suffixip, T.idoverride, T.version FROM student_tunnel_tokens T INNER JOIN (SELECT B.id_student, MAX(B.time) AS time, B.idoverride FROM student_tunnel_tokens B WHERE B.pubkey IS NOT NULL GROUP BY id_student, idoverride) L ON T.id_student = L.id_student AND T.time = L.time"); errr != nil { return nil, errr } else { defer rows.Close() for rows.Next() { t := &TunnelToken{} - if err = rows.Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.Version); err != nil { + if err = rows.Scan(&t.token, &t.TokenText, &t.IdStudent, &t.PubKey, &t.Time, &t.SuffixIP, &t.OverrideID, &t.Version); err != nil { return } ts = append(ts, t) diff --git a/token-validator/check.go b/token-validator/check.go index c6cadd2..7fdaeb0 100644 --- a/token-validator/check.go +++ b/token-validator/check.go @@ -28,7 +28,7 @@ func init() { })) } func check_GLUE_respond(student *adlin.Student, domain string, ip string) (err error) { - if !strings.HasPrefix(ip, adlin.StudentIP(student.Id).String()) { + if !strings.HasPrefix(ip, adlin.StudentIP(student.Id, 0).String()) { return fmt.Errorf("%q is not your IP range", ip) } diff --git a/token-validator/domain.go b/token-validator/domain.go index 61cfd0c..18d8deb 100644 --- a/token-validator/domain.go +++ b/token-validator/domain.go @@ -312,8 +312,8 @@ func AddAssociatedDomains(student *adlin.Student, aaaa net.IP) (err error) { } if aaaa == nil { - aaaa = net.ParseIP(adlin.StudentIP(student.Id).String() + "1") - } else if !adlin.StudentNet(student.Id).Contains(aaaa) { + aaaa = net.ParseIP(adlin.StudentIP(student.Id, 0).String() + "1") + } else if !adlin.StudentNet(student.Id, 0).Contains(aaaa) { return errors.New("The associated IP has to be in your IP range.") } diff --git a/token-validator/ip.go b/token-validator/ip.go index 8944ec2..9805562 100644 --- a/token-validator/ip.go +++ b/token-validator/ip.go @@ -57,7 +57,7 @@ func showIPs(_ httprouter.Params, body []byte) (interface{}, error) { func GetStudentTunnelIPs(student *adlin.Student) (ips []string) { if ts, err := student.GetActivesTunnels(); err != nil || len(ts) == 0 || ts[0].SuffixIP == 0 { - ips = append(ips, adlin.StudentIP(student.Id).String()+"1") + ips = append(ips, adlin.StudentIP(student.Id, 0).String()+"1") } else { for _, t := range ts { ips = append(ips, t.GetStudentIP()) diff --git a/token-validator/wg.go b/token-validator/wg.go index 03d4f6e..d564dd3 100644 --- a/token-validator/wg.go +++ b/token-validator/wg.go @@ -31,7 +31,7 @@ func init() { }) router.GET("/api/wg/", apiAuthHandler(showWgTunnel)) router.GET("/api/wginfo", apiAuthHandler(func(student *adlin.Student, ps httprouter.Params, body []byte) (interface{}, error) { - return getTunnelInfo(student.Id), nil + return getTunnelInfo(student.Id, 0), nil })) router.POST("/api/wg/", apiAuthHandler(genWgToken)) router.GET("/api/wg/:token", getWgTunnelInfo) @@ -59,13 +59,13 @@ type TunnelInfo struct { SrvGW6 string `json:"srv_gw6"` } -func getTunnelInfo(student int64) TunnelInfo { +func getTunnelInfo(student int64, idoverride int) TunnelInfo { srv_pubkey, _ := base64.StdEncoding.DecodeString("uSpqyYovvP4OG6wDxZ0Qkq45MfyK58PMUuPaLesY8FI=") return TunnelInfo{ Status: "OK", SrvPubKey: srv_pubkey, SrvPort: 42912, - CltIPv6: adlin.StudentIP(student), + CltIPv6: adlin.StudentIP(student, idoverride), CltRange: adlin.StdNetmask, SrvGW6: "2a01:e0a:2b:2252::1", } @@ -133,7 +133,7 @@ func getWgTunnelInfo(w http.ResponseWriter, r *http.Request, ps httprouter.Param syncWgConf() - tinfo := getTunnelInfo(token.IdStudent) + tinfo := getTunnelInfo(token.IdStudent, token.OverrideID) var student *adlin.Student student, err = adlin.GetStudent(int(token.IdStudent)) @@ -218,7 +218,7 @@ func GenWGConfig(w io.Writer) error { #IdStudent = %d PublicKey = %s AllowedIPs = %s/%d -`, t.IdStudent, base64.StdEncoding.EncodeToString(t.PubKey), adlin.StudentIP(t.IdStudent), 80))) +`, t.IdStudent, base64.StdEncoding.EncodeToString(t.PubKey), adlin.StudentIP(t.IdStudent, t.OverrideID), 80))) } return nil