done 2020

This commit is contained in:
nemunaire 2020-02-21 00:16:22 +01:00
parent 7682cae26c
commit 1d2199aaef
6 changed files with 89 additions and 63 deletions

View file

@ -9,19 +9,24 @@ import (
"errors" "errors"
"fmt" "fmt"
"log" "log"
"net"
"os" "os"
"os/exec" "os/exec"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/miekg/dns"
) )
const ( const (
AssociatedDomainSuffix = "adlin2020.p0m.fr" AssociatedDomainSuffix = "adlin2020.p0m.fr."
DelegatedDomainSuffix = "srs.p0m.fr" DelegatedDomainSuffix = "srs.p0m.fr."
) )
var tsigSecret = map[string]string{"ddns.": ""}
func init() { func init() {
router.GET("/api/adomains/", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.GET("/api/adomains/", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.GetAssociatedDomains(), nil return student.GetAssociatedDomains(), nil
@ -47,21 +52,21 @@ func init() {
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.AddNSDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values[0]) return true, student.AddNSDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values)
})) }))
router.PATCH("/api/ddomains/:dn/NS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.PATCH("/api/ddomains/:dn/NS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry var ue Entry
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.UpdateNSDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.ValuesFrom[0], ue.Values[0]) return true, student.UpdateNSDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.ValuesFrom, ue.Values)
})) }))
router.DELETE("/api/ddomains/:dn/NS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.DELETE("/api/ddomains/:dn/NS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry var ue Entry
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "NS", ue.Values...) return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "NS", ue.Values)
})) }))
router.GET("/api/ddomains/:dn/GLUE", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.GET("/api/ddomains/:dn/GLUE", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.getRRDelegatedDomain(ps.ByName("dn"), "AAAA") return student.getRRDelegatedDomain(ps.ByName("dn"), "AAAA")
@ -71,28 +76,28 @@ func init() {
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.AddGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values[0]) return true, student.AddGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.Values)
})) }))
router.PATCH("/api/ddomains/:dn/AAAA", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.PATCH("/api/ddomains/:dn/AAAA", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry var ue Entry
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.UpdateGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.ValuesFrom[0], ue.Values[0]) return true, student.UpdateGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.ValuesFrom, ue.Values)
})) }))
router.POST("/api/ddomains/:dn/GLUE", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.POST("/api/ddomains/:dn/GLUE", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry var ue Entry
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.UpdateGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.ValuesFrom[0], ue.Values[0]) return true, student.UpdateGLUEDelegatedDomain(ps.ByName("dn"), ue.TTL, ue.ValuesFrom, ue.Values)
})) }))
router.DELETE("/api/ddomains/:dn/AAAA", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.DELETE("/api/ddomains/:dn/AAAA", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
var ue Entry var ue Entry
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "AAAA", ue.Values...) return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "AAAA", ue.Values)
})) }))
router.GET("/api/ddomains/:dn/DS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) { router.GET("/api/ddomains/:dn/DS", apiAuthHandler(func (student Student, ps httprouter.Params, body []byte) (interface{}, error) {
return student.getRRDelegatedDomain(ps.ByName("dn"), "DS") return student.getRRDelegatedDomain(ps.ByName("dn"), "DS")
@ -116,16 +121,16 @@ func init() {
if err := json.Unmarshal(body, &ue); err != nil { if err := json.Unmarshal(body, &ue); err != nil {
return nil, err return nil, err
} }
return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "DS", ue.Values...) return true, student.DeleteRRDelegatedDomain(ps.ByName("dn"), "DS", ue.Values)
})) }))
} }
type Entry struct { type Entry struct {
Domain string `json:"domain"` Domain string `json:"domain"`
TTL uint64 `json:"ttl"` TTL uint32 `json:"ttl"`
RR string `json:"rr"` RR string `json:"rr"`
ValuesFrom []string `json:"valuesfrom,omitempty"` ValuesFrom string `json:"valuesfrom,omitempty"`
Values []string `json:"values"` Values string `json:"values"`
} }
func runKnotc(args ...string) (out []byte, err error) { func runKnotc(args ...string) (out []byte, err error) {
@ -137,21 +142,27 @@ func runKnotc(args ...string) (out []byte, err error) {
return cmd.CombinedOutput() return cmd.CombinedOutput()
} }
func parseKnotZoneRead(args ...string) (rr []Entry, err error) { func parseKnotZoneRead(globalDomain string, domain string) (rr []Entry, err error) {
var out []byte t := new(dns.Transfer)
args = append([]string{"zone-read"}, args...)
out, err = runKnotc(args...)
for _, line := range strings.Split(string(out), "\n") { m := new(dns.Msg)
cols := strings.Fields(line) t.TsigSecret = tsigSecret
if len(cols) >= 5 { m.SetAxfr(globalDomain)
var ttl uint64 m.SetTsig("ddns.", dns.HmacSHA256, 300, time.Now().Unix())
ttl, err = strconv.ParseUint(cols[2], 10, 64)
if err != nil { c, err := t.In(m, "127.0.0.1:53")
return if err != nil {
log.Println(globalDomain, err)
return nil, err
}
for l := range c {
for _, r := range l.RR {
var z dns.RFC3597
z.ToRFC3597(r)
if strings.HasSuffix(r.Header().Name, domain) {
rr = append(rr, Entry{r.Header().Name, r.Header().Ttl, dns.TypeToString[r.Header().Rrtype], "", z.Rdata})
} }
rr = append(rr, Entry{cols[1], ttl, cols[3], nil, cols[4:]})
} }
} }
@ -159,15 +170,13 @@ func parseKnotZoneRead(args ...string) (rr []Entry, err error) {
} }
func (student Student) myAssociatedDomain() (string) { func (student Student) myAssociatedDomain() (string) {
return fmt.Sprintf("%s.%s.", strings.Trim(strings.Replace(student.Login, "_", "-", -1), "-_"), AssociatedDomainSuffix) return fmt.Sprintf("%s.%s", strings.Trim(strings.Replace(student.Login, "_", "-", -1), "-_"), AssociatedDomainSuffix)
} }
func (student Student) GetAssociatedDomains() (ds []string) { func (student Student) GetAssociatedDomains() (ds []string) {
studentDomain := student.myAssociatedDomain() studentDomain := student.myAssociatedDomain()
if _, err := parseKnotZoneRead(AssociatedDomainSuffix, studentDomain); err == nil { ds = append(ds, studentDomain)
ds = append(ds, studentDomain)
}
return return
} }
@ -199,30 +208,43 @@ func (student Student) GetAssociatedDomain(dn string) (rrs []Entry, err error) {
} }
func (student Student) AddAssociatedDomains() (err error) { func (student Student) AddAssociatedDomains() (err error) {
for _, d := range []string{student.myAssociatedDomain()} { m1 := new(dns.Msg)
for _, cmd := range [][]string{ m1.Id = dns.Id()
[]string{"zone-begin", AssociatedDomainSuffix}, m1.Opcode = dns.OpcodeUpdate
[]string{"zone-set", AssociatedDomainSuffix, d, "900", "A", "82.64.31.248"}, m1.Question = make([]dns.Question, 1)
[]string{"zone-set", AssociatedDomainSuffix, d, "900", "AAAA", studentIP(student.Id) + "1"}, m1.Question[0] = dns.Question{AssociatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
[]string{"zone-commit", AssociatedDomainSuffix},
} { rrAd := new(dns.A)
var out []byte rrAd.Hdr = dns.RR_Header{Name: student.myAssociatedDomain(), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
out, err = runKnotc(cmd...) m1.Remove([]dns.RR{rrAd})
if err != nil {
log.Printf("An error occurs on command '%s': %s", strings.Join(cmd, " "), err.Error()) rrA := new(dns.A)
err = errors.New(string(out)) rrA.Hdr = dns.RR_Header{Name: student.myAssociatedDomain(), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 3600}
runKnotc("zone-abort", AssociatedDomainSuffix) rrA.A = net.IPv4(82, 64, 31, 248)
return m1.Insert([]dns.RR{rrA})
}
} rrAAAAd := new(dns.AAAA)
} rrAAAAd.Hdr = dns.RR_Header{Name: student.myAssociatedDomain(), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0}
m1.Remove([]dns.RR{rrAAAAd})
rrAAAA := new(dns.AAAA)
rrAAAA.Hdr = dns.RR_Header{Name: student.myAssociatedDomain(), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 3600}
rrAAAA.AAAA = studentIP(student.Id)
rrAAAA.AAAA[15] = 1
m1.Insert([]dns.RR{rrAAAA})
c := new(dns.Client)
c.TsigSecret = tsigSecret
m1.SetTsig("ddns.", dns.HmacSHA256, 300, time.Now().Unix())
_, _, err = c.Exchange(m1, "127.0.0.1:53")
return return
} }
func (student Student) MyDelegatedDomain() (string) { func (student Student) MyDelegatedDomain() (string) {
return fmt.Sprintf("%s.%s.", strings.Trim(strings.Replace(student.Login, "_", "-", -1), "-_"), DelegatedDomainSuffix) return fmt.Sprintf("%s.%s", strings.Trim(strings.Replace(student.Login, "_", "-", -1), "-_"), DelegatedDomainSuffix)
} }
func (student Student) getRRDelegatedDomain(dn string, rr string) (rrs []Entry, err error) { func (student Student) getRRDelegatedDomain(dn string, rr string) (rrs []Entry, err error) {
@ -238,7 +260,7 @@ func (student Student) getRRDelegatedDomain(dn string, rr string) (rrs []Entry,
err = errors.New(fmt.Sprintf("Unable to find domain %q.", dn)) err = errors.New(fmt.Sprintf("Unable to find domain %q.", dn))
} }
if entries, errr := parseKnotZoneRead(DelegatedDomainSuffix); err != nil { if entries, errr := parseKnotZoneRead(DelegatedDomainSuffix, dn); err != nil {
return nil, errr return nil, errr
} else { } else {
for _, e := range entries { for _, e := range entries {
@ -251,7 +273,7 @@ func (student Student) getRRDelegatedDomain(dn string, rr string) (rrs []Entry,
return return
} }
func (student Student) AddNSDelegatedDomain(dn string, ttl uint64, ns string) (err error) { func (student Student) AddNSDelegatedDomain(dn string, ttl uint32, ns string) (err error) {
for _, d := range []string{student.MyDelegatedDomain()} { for _, d := range []string{student.MyDelegatedDomain()} {
for _, cmd := range [][]string{ for _, cmd := range [][]string{
[]string{"zone-begin", DelegatedDomainSuffix}, []string{"zone-begin", DelegatedDomainSuffix},
@ -272,7 +294,7 @@ func (student Student) AddNSDelegatedDomain(dn string, ttl uint64, ns string) (e
return return
} }
func (student Student) UpdateNSDelegatedDomain(dn string, ttl uint64, oldns string, ns string) (err error) { func (student Student) UpdateNSDelegatedDomain(dn string, ttl uint32, oldns string, ns string) (err error) {
for _, d := range []string{student.MyDelegatedDomain()} { for _, d := range []string{student.MyDelegatedDomain()} {
for _, cmd := range [][]string{ for _, cmd := range [][]string{
[]string{"zone-begin", DelegatedDomainSuffix}, []string{"zone-begin", DelegatedDomainSuffix},
@ -295,7 +317,7 @@ func (student Student) UpdateNSDelegatedDomain(dn string, ttl uint64, oldns stri
} }
func (student Student) AddGLUEDelegatedDomain(dn string, ttl uint64, aaaa string) (err error) { func (student Student) AddGLUEDelegatedDomain(dn string, ttl uint32, aaaa string) (err error) {
domains := []string{student.MyDelegatedDomain()} domains := []string{student.MyDelegatedDomain()}
found := false found := false
for _, d := range domains { for _, d := range domains {
@ -327,7 +349,7 @@ func (student Student) AddGLUEDelegatedDomain(dn string, ttl uint64, aaaa string
return return
} }
func (student Student) UpdateGLUEDelegatedDomain(dn string, ttl uint64, oldaaaa string, aaaa string) (err error) { func (student Student) UpdateGLUEDelegatedDomain(dn string, ttl uint32, oldaaaa string, aaaa string) (err error) {
domains := []string{student.MyDelegatedDomain()} domains := []string{student.MyDelegatedDomain()}
found := false found := false
for _, d := range domains { for _, d := range domains {
@ -362,7 +384,9 @@ func (student Student) UpdateGLUEDelegatedDomain(dn string, ttl uint64, oldaaaa
} }
func (student Student) AddDSDelegatedDomain(dn string, ttl uint64, dnskey []string) (err error) { func (student Student) AddDSDelegatedDomain(dn string, ttl uint32, rdata string) (err error) {
dnskey := strings.Split(rdata, " ")
if len(dnskey) != 4 { if len(dnskey) != 4 {
return errors.New("Wrong number of value for this record") return errors.New("Wrong number of value for this record")
} }
@ -411,12 +435,12 @@ func (student Student) AddDSDelegatedDomain(dn string, ttl uint64, dnskey []stri
return return
} }
func (student Student) UpdateDSDelegatedDomain(dn string, ttl uint64, oldds []string, ds []string) (err error) { func (student Student) UpdateDSDelegatedDomain(dn string, ttl uint32, oldds string, ds string) (err error) {
for _, d := range []string{student.MyDelegatedDomain()} { for _, d := range []string{student.MyDelegatedDomain()} {
for _, cmd := range [][]string{ for _, cmd := range [][]string{
[]string{"zone-begin", DelegatedDomainSuffix}, []string{"zone-begin", DelegatedDomainSuffix},
[]string{"zone-unset", DelegatedDomainSuffix, d, "DS", strings.Join(oldds, " ")}, []string{"zone-unset", DelegatedDomainSuffix, d, "DS", oldds},
[]string{"zone-set", DelegatedDomainSuffix, d, fmt.Sprintf("%d", ttl), "DS", strings.Join(ds, " ")}, []string{"zone-set", DelegatedDomainSuffix, d, fmt.Sprintf("%d", ttl), "DS", ds},
[]string{"zone-commit", DelegatedDomainSuffix}, []string{"zone-commit", DelegatedDomainSuffix},
} { } {
var out []byte var out []byte

View file

@ -304,6 +304,7 @@ angular.module("AdLinApp")
} }
$scope.saveNSRR = function(nsrr) { $scope.saveNSRR = function(nsrr) {
nsrr.values = nsrr.values.join(" ");
$http({ $http({
method: (nsrr.valuesfrom !== undefined)?'PATCH':'POST', method: (nsrr.valuesfrom !== undefined)?'PATCH':'POST',
url: "/api/ddomains/" + nsrr.domain + "/" + nsrr.rr, url: "/api/ddomains/" + nsrr.domain + "/" + nsrr.rr,

View file

@ -45,7 +45,7 @@ func getStudentIPs(student Student) (r map[string]string) {
r["vlan0"] = fmt.Sprintf("172.23.0.%d", student.IPSuffix()) r["vlan0"] = fmt.Sprintf("172.23.0.%d", student.IPSuffix())
r["vlan7"] = fmt.Sprintf("172.23.142.%d", student.IPSuffix()) r["vlan7"] = fmt.Sprintf("172.23.142.%d", student.IPSuffix())
r["wg"] = studentIP(student.Id) r["wg"] = studentIP(student.Id).String()
r["adn"] = student.myAssociatedDomain() r["adn"] = student.myAssociatedDomain()
r["ddn"] = student.MyDelegatedDomain() r["ddn"] = student.MyDelegatedDomain()

View file

@ -9,6 +9,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"net"
"net/http" "net/http"
"os/exec" "os/exec"
"strings" "strings"
@ -49,7 +50,7 @@ type TunnelInfo struct {
Status string `json:"status"` Status string `json:"status"`
SrvPubKey []byte `json:"srv_pubkey"` SrvPubKey []byte `json:"srv_pubkey"`
SrvPort uint16 `json:"srv_port"` SrvPort uint16 `json:"srv_port"`
CltIPv6 string `json:"clt_ipv6"` CltIPv6 net.IP `json:"clt_ipv6"`
CltRange uint8 `json:"clt_range"` CltRange uint8 `json:"clt_range"`
SrvGW6 string `json:"srv_gw6"` SrvGW6 string `json:"srv_gw6"`
} }
@ -241,8 +242,8 @@ func GetStudentsTunnels() (ts []TunnelToken, err error) {
} }
} }
func studentIP(idstd int64) string { func studentIP(idstd int64) net.IP {
return fmt.Sprintf("2a01:e0a:2b:2252:%x::", idstd) return net.ParseIP(fmt.Sprintf("2a01:e0a:2b:2252:%x::", idstd))
} }
func GenWGConfig(w io.Writer) (error) { func GenWGConfig(w io.Writer) (error) {

View file

@ -232,7 +232,7 @@ services:
binds: binds:
- /etc/dresolv.conf:/etc/resolv.conf - /etc/dresolv.conf:/etc/resolv.conf
- name: ns-resolv - name: ns-resolv
image: nemunaire/unbound:528445043685979b1b479c6c44d68de36bc872ad image: nemunaire/unbound:7fa2ef501be79db472de64f451b250173ace5ecf
net: /run/netns/ns net: /run/netns/ns
capabilities: capabilities:
- all - all

View file

@ -10,7 +10,7 @@ abstract: |
\vspace{1em} \vspace{1em}
Tous les éléments de ce TP (exercices et projet) sont à rendre à Tous les éléments de ce TP (exercices et projet) sont à rendre à
<adlin@nemunai.re> au plus tard le dimanche 14 avril 2019 à 23 <adlin@nemunai.re> au plus tard le dimanche 21 avril 2019 à 23
h 42. Consultez la dernière section de chaque partie pour plus d'information h 42. Consultez la dernière section de chaque partie pour plus d'information
sur les éléments à rendre. sur les éléments à rendre.