Introduce overrideID option to allow multiple tunnels in parellel

This commit is contained in:
nemunaire 2022-04-30 02:41:12 +02:00
parent 9043bafe3d
commit 7187a7d187
6 changed files with 32 additions and 30 deletions

View File

@ -141,6 +141,7 @@ CREATE TABLE IF NOT EXISTS student_tunnel_tokens(
time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
pubkey BLOB(50) DEFAULT NULL, pubkey BLOB(50) DEFAULT NULL,
suffixip INTEGER NOT NULL, suffixip INTEGER NOT NULL,
idoverride INTEGER NOT NULL DEFAULT 0,
version INTEGER NOT NULL, version INTEGER NOT NULL,
FOREIGN KEY(id_student) REFERENCES students(id_student) FOREIGN KEY(id_student) REFERENCES students(id_student)
) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin; ) DEFAULT CHARACTER SET = utf8 COLLATE = utf8_bin;

View File

@ -28,13 +28,13 @@ func GetCollectorPublic() ed25519.PublicKey {
return collector_secret.Public().(ed25519.PublicKey) return collector_secret.Public().(ed25519.PublicKey)
} }
func StudentIP(idstd int64) net.IP { func StudentIP(idstd int64, overrideid int) net.IP {
return net.ParseIP(fmt.Sprintf("2a01:e0a:2b:2252:%x::", idstd)) 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{ return &net.IPNet{
IP: StudentIP(idstd), IP: StudentIP(idstd, overrideid),
Mask: net.CIDRMask(StdNetmask, 128), Mask: net.CIDRMask(StdNetmask, 128),
} }
} }
@ -113,12 +113,13 @@ func readWgDump() (wgd map[string]*WGDump, err error) {
} }
type TunnelToken struct { type TunnelToken struct {
token []byte token []byte
TokenText string TokenText string
IdStudent int64 IdStudent int64
PubKey []byte PubKey []byte
Time time.Time Time time.Time
SuffixIP int SuffixIP int
OverrideID int
// Version stores the TP number where the token is used // Version stores the TP number where the token is used
Version int Version int
Dump *WGDump Dump *WGDump
@ -126,14 +127,14 @@ type TunnelToken struct {
func (tt *TunnelToken) GetStudentIP() string { func (tt *TunnelToken) GetStudentIP() string {
if tt.SuffixIP == 0 { 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 { } 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 { 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 { func (tt *TunnelToken) GenKeySign() []byte {
@ -151,7 +152,7 @@ func TokenFromText(token string) []byte {
func GetTunnelToken(token []byte) (t *TunnelToken, err error) { func GetTunnelToken(token []byte) (t *TunnelToken, err error) {
t = new(TunnelToken) 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 err == nil && t.PubKey != nil {
if wgd, errr := readWgDump(); errr == nil { if wgd, errr := readWgDump(); errr == nil {
if v, ok := wgd[base64.StdEncoding.EncodeToString(t.PubKey)]; ok { 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) { 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 return nil, errr
} else if wgd, errr := readWgDump(); errr != nil { } else if wgd, errr := readWgDump(); errr != nil {
return nil, errr return nil, errr
@ -187,7 +188,7 @@ func (student *Student) GetTunnelTokens() (ts []*TunnelToken, err error) {
for rows.Next() { for rows.Next() {
t := &TunnelToken{} 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 return
} }
if t.PubKey != nil { if t.PubKey != nil {
@ -206,7 +207,7 @@ func (student *Student) GetTunnelTokens() (ts []*TunnelToken, err error) {
} }
func (student *Student) GetActivesTunnels() (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 return nil, errr
} else if wgd, errr := readWgDump(); errr != nil { } else if wgd, errr := readWgDump(); errr != nil {
return nil, errr return nil, errr
@ -215,7 +216,7 @@ func (student *Student) GetActivesTunnels() (ts []*TunnelToken, err error) {
for rows.Next() { for rows.Next() {
t := &TunnelToken{} 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 return
} }
if t.PubKey != nil { 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) { func (student *Student) GetTunnelToken(token []byte) (t *TunnelToken, err error) {
t = new(TunnelToken) 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 err == nil && t.PubKey != nil {
if wgd, errr := readWgDump(); errr == nil { if wgd, errr := readWgDump(); errr == nil {
if v, ok := wgd[base64.StdEncoding.EncodeToString(t.PubKey)]; ok { 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) { 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 return nil, errr
} else { } else {
defer rows.Close() defer rows.Close()
for rows.Next() { for rows.Next() {
t := &TunnelToken{} 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 return
} }
ts = append(ts, t) ts = append(ts, t)

View File

@ -28,7 +28,7 @@ func init() {
})) }))
} }
func check_GLUE_respond(student *adlin.Student, domain string, ip string) (err error) { 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) return fmt.Errorf("%q is not your IP range", ip)
} }

View File

@ -312,8 +312,8 @@ func AddAssociatedDomains(student *adlin.Student, aaaa net.IP) (err error) {
} }
if aaaa == nil { if aaaa == nil {
aaaa = net.ParseIP(adlin.StudentIP(student.Id).String() + "1") aaaa = net.ParseIP(adlin.StudentIP(student.Id, 0).String() + "1")
} else if !adlin.StudentNet(student.Id).Contains(aaaa) { } else if !adlin.StudentNet(student.Id, 0).Contains(aaaa) {
return errors.New("The associated IP has to be in your IP range.") return errors.New("The associated IP has to be in your IP range.")
} }

View File

@ -57,7 +57,7 @@ func showIPs(_ httprouter.Params, body []byte) (interface{}, error) {
func GetStudentTunnelIPs(student *adlin.Student) (ips []string) { func GetStudentTunnelIPs(student *adlin.Student) (ips []string) {
if ts, err := student.GetActivesTunnels(); err != nil || len(ts) == 0 || ts[0].SuffixIP == 0 { 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 { } else {
for _, t := range ts { for _, t := range ts {
ips = append(ips, t.GetStudentIP()) ips = append(ips, t.GetStudentIP())

View File

@ -31,7 +31,7 @@ func init() {
}) })
router.GET("/api/wg/", apiAuthHandler(showWgTunnel)) router.GET("/api/wg/", apiAuthHandler(showWgTunnel))
router.GET("/api/wginfo", apiAuthHandler(func(student *adlin.Student, ps httprouter.Params, body []byte) (interface{}, error) { 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.POST("/api/wg/", apiAuthHandler(genWgToken))
router.GET("/api/wg/:token", getWgTunnelInfo) router.GET("/api/wg/:token", getWgTunnelInfo)
@ -59,13 +59,13 @@ type TunnelInfo struct {
SrvGW6 string `json:"srv_gw6"` SrvGW6 string `json:"srv_gw6"`
} }
func getTunnelInfo(student int64) TunnelInfo { func getTunnelInfo(student int64, idoverride int) TunnelInfo {
srv_pubkey, _ := base64.StdEncoding.DecodeString("uSpqyYovvP4OG6wDxZ0Qkq45MfyK58PMUuPaLesY8FI=") srv_pubkey, _ := base64.StdEncoding.DecodeString("uSpqyYovvP4OG6wDxZ0Qkq45MfyK58PMUuPaLesY8FI=")
return TunnelInfo{ return TunnelInfo{
Status: "OK", Status: "OK",
SrvPubKey: srv_pubkey, SrvPubKey: srv_pubkey,
SrvPort: 42912, SrvPort: 42912,
CltIPv6: adlin.StudentIP(student), CltIPv6: adlin.StudentIP(student, idoverride),
CltRange: adlin.StdNetmask, CltRange: adlin.StdNetmask,
SrvGW6: "2a01:e0a:2b:2252::1", SrvGW6: "2a01:e0a:2b:2252::1",
} }
@ -133,7 +133,7 @@ func getWgTunnelInfo(w http.ResponseWriter, r *http.Request, ps httprouter.Param
syncWgConf() syncWgConf()
tinfo := getTunnelInfo(token.IdStudent) tinfo := getTunnelInfo(token.IdStudent, token.OverrideID)
var student *adlin.Student var student *adlin.Student
student, err = adlin.GetStudent(int(token.IdStudent)) student, err = adlin.GetStudent(int(token.IdStudent))
@ -218,7 +218,7 @@ func GenWGConfig(w io.Writer) error {
#IdStudent = %d #IdStudent = %d
PublicKey = %s PublicKey = %s
AllowedIPs = %s/%d 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 return nil