Compare commits

..

No commits in common. "a52bf0e52d9ffedaf7a953d3a946c16f567cb153" and "caaa30c7478b70c7402c429771dffde03ece6888" have entirely different histories.

12 changed files with 42 additions and 278 deletions

View File

@ -19,7 +19,6 @@ import (
const ( const (
DEFAULT_RESOLVER = "2a01:e0a:2b:2250::1" DEFAULT_RESOLVER = "2a01:e0a:2b:2250::1"
year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. Taken from miekg/dns
) )
var verbose = false var verbose = false
@ -89,11 +88,9 @@ func check_dns(domain, ip string) (aaaa net.IP, err error) {
if r == nil { if r == nil {
err = errors.New("response is nil") err = errors.New("response is nil")
return
} }
if r.Rcode != dns.RcodeSuccess { if r.Rcode != dns.RcodeSuccess {
err = errors.New("failed to get a valid answer") err = errors.New("failed to get a valid answer")
return
} }
for _, answer := range r.Answer { for _, answer := range r.Answer {
@ -105,168 +102,6 @@ func check_dns(domain, ip string) (aaaa net.IP, err error) {
return return
} }
func check_dnssec(domain, ip string) (err error) {
client := dns.Client{Net: "tcp", Timeout: time.Second * 10}
// Get DNSKEY
m := new(dns.Msg)
m.SetEdns0(4096, true)
m.SetQuestion(domain, dns.TypeDNSKEY)
var r *dns.Msg
r, _, err = client.Exchange(m, fmt.Sprintf("[%s]:53", ip))
if err != nil {
return
}
if r == nil {
return errors.New("response is nil")
}
if r.Rcode != dns.RcodeSuccess {
return errors.New("failed to get a valid answer when getting DNSKEY")
}
var rrs []dns.RR
var dnskeys []*dns.DNSKEY
var dnskeysig *dns.RRSIG
for _, answer := range r.Answer {
if t, ok := answer.(*dns.DNSKEY); ok {
dnskeys = append(dnskeys, t)
rrs = append(rrs, dns.RR(t))
} else if t, ok := answer.(*dns.RRSIG); ok {
dnskeysig = t
}
}
if dnskeysig == nil {
return fmt.Errorf("Unable to verify DNSKEY record signature: No RRSIG found for DNSKEY record.")
}
found := false
for _, dnskey := range dnskeys {
if err = dnskeysig.Verify(dnskey, rrs); err == nil {
found = true
break
}
}
if !found {
return fmt.Errorf("Unable to verify DNSKEY record signature: %w", err)
}
// Check AAAA validity
m = new(dns.Msg)
m.SetEdns0(4096, true)
m.SetQuestion(domain, dns.TypeAAAA)
r, _, err = client.Exchange(m, fmt.Sprintf("[%s]:53", ip))
if err != nil {
return
}
if r == nil {
return errors.New("response is nil")
}
if r.Rcode != dns.RcodeSuccess {
return errors.New("failed to get a valid answer when getting AAAA records")
}
rrs = []dns.RR{}
var aaaas []*dns.AAAA
var aaaasig *dns.RRSIG
for _, answer := range r.Answer {
if t, ok := answer.(*dns.AAAA); ok {
aaaas = append(aaaas, t)
rrs = append(rrs, t)
} else if t, ok := answer.(*dns.RRSIG); ok {
aaaasig = t
}
}
if len(aaaas) == 0 {
return errors.New("Something odd happen: no AAAA record found.")
}
if aaaasig == nil {
return fmt.Errorf("Unable to verify AAAA record signature: No RRSIG found for AAAA record.")
}
found = false
for _, dnskey := range dnskeys {
if err = aaaasig.Verify(dnskey, rrs); err == nil {
found = true
if !aaaasig.ValidityPeriod(time.Now()) {
utc := time.Now().UTC().Unix()
modi := (int64(aaaasig.Inception) - utc) / year68
ti := int64(aaaasig.Inception) + modi*year68
mode := (int64(aaaasig.Expiration) - utc) / year68
te := int64(aaaasig.Expiration) + mode*year68
if ti > utc {
return fmt.Errorf("Unable to verify AAAA record signature: signature not yet valid")
} else if utc > te {
return fmt.Errorf("Unable to verify AAAA record signature: signature expired")
} else {
return fmt.Errorf("Unable to verify AAAA record signature: signature expired or not yet valid")
}
}
break
}
}
if !found {
return fmt.Errorf("Unable to verify AAAA record signature: %w", err)
}
// Check DS
m = new(dns.Msg)
m.SetQuestion(domain, dns.TypeDS)
m.RecursionDesired = false
m.SetEdns0(4096, true)
r, _, err = client.Exchange(m, "[2a01:e0a:2b:2250::b]:53")
if err != nil {
return
}
if r == nil {
return errors.New("response is nil")
}
if r.Rcode != dns.RcodeSuccess {
return errors.New("failed to get a valid answer when getting DS records in parent server")
}
found = false
for _, answer := range r.Answer {
if t, ok := answer.(*dns.DS); ok {
for _, dnskey := range dnskeys {
expectedDS := dnskey.ToDS(dns.SHA256)
if expectedDS.KeyTag == t.KeyTag && expectedDS.Algorithm == t.Algorithm && expectedDS.DigestType == t.DigestType && expectedDS.Digest == t.Digest {
found = true
err = nil
break
} else {
err = fmt.Errorf("DS record found in parent zone differs from DNSKEY %v vs. %v.", expectedDS, t)
}
}
}
}
if !found {
if err == nil {
return fmt.Errorf("Unable to find a valid DS record in parent zone.")
} else {
return err
}
}
return
}
// PORT 80 // PORT 80
func check_http(ip, dn string) (err error) { func check_http(ip, dn string) (err error) {
@ -335,7 +170,6 @@ func check_https(domain, ip string) (err error) {
type matrix_result struct { type matrix_result struct {
WellKnownResult struct { WellKnownResult struct {
Server string `json:"m.server"`
Result string `json:"result"` Result string `json:"result"`
} }
DNSResult struct { DNSResult struct {
@ -353,7 +187,7 @@ type matrix_result struct {
Name string `json:"name"` Name string `json:"name"`
Version string `json:"version"` Version string `json:"version"`
} }
FederationOK bool `json:"FederationOK"` FederationOK bool
} }
func check_matrix(domain string) (version string, err error) { func check_matrix(domain string) (version string, err error) {
@ -365,16 +199,16 @@ func check_matrix(domain string) (version string, err error) {
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode >= 300 { if resp.StatusCode >= 300 {
return "", fmt.Errorf("Sorry, the federation tester is broken. Check on https://federationtester.matrix.org/#%s", strings.TrimSuffix(domain, ".")) return "", fmt.Errorf("Sorry, the federation tester is broken. Check on https://federationtester.matrix.org/#%s", domain)
} }
var federationTest matrix_result var federationTest matrix_result
if err = json.NewDecoder(resp.Body).Decode(&federationTest); err != nil { if federationTest.FederationOK {
log.Printf("Error in check_matrix, when decoding json: %w", err.Error())
return "", fmt.Errorf("Sorry, the federation tester is broken. Check on https://federationtester.matrix.org/#%s", strings.TrimSuffix(domain, "."))
} else if federationTest.FederationOK {
version = federationTest.Version.Name + " " + federationTest.Version.Version version = federationTest.Version.Name + " " + federationTest.Version.Version
return version, nil return version, nil
} else if err = json.NewDecoder(resp.Body).Decode(&federationTest); err != nil {
log.Printf("Error in chech_matrix, when decoding json:", err.Error())
return "", fmt.Errorf("Sorry, the federation tester is broken. Check on https://federationtester.matrix.org/#%s", domain)
} else if federationTest.DNSResult.SRVError != nil && federationTest.WellKnownResult.Result != "" { } else if federationTest.DNSResult.SRVError != nil && federationTest.WellKnownResult.Result != "" {
return "", fmt.Errorf("%s OR %s", federationTest.DNSResult.SRVError.Message, federationTest.WellKnownResult.Result) return "", fmt.Errorf("%s OR %s", federationTest.DNSResult.SRVError.Message, federationTest.WellKnownResult.Result)
} else if len(federationTest.ConnectionErrors) > 0 { } else if len(federationTest.ConnectionErrors) > 0 {
@ -388,10 +222,8 @@ func check_matrix(domain string) (version string, err error) {
msg.WriteString(cerr.Message) msg.WriteString(cerr.Message)
} }
return "", fmt.Errorf("Connection errors: %s", msg.String()) return "", fmt.Errorf("Connection errors: %s", msg.String())
} else if federationTest.WellKnownResult.Server != strings.TrimSuffix(domain, ".") {
return "", fmt.Errorf("Bad homeserver_name: got %s, expected %s.", federationTest.WellKnownResult.Server, strings.TrimSuffix(domain, "."))
} else { } else {
return "", fmt.Errorf("An unimplemented error occurs. Please report to nemunaire. But know that federation seems to be broken. Check https://federationtester.matrix.org/#%s", strings.TrimSuffix(domain, ".")) return "", fmt.Errorf("An unimplemented error occurs. Please report to nemunaire. But know that federation seems to be broken. Check https://federationtester.matrix.org/#%s", domain)
} }
} }
@ -516,7 +348,7 @@ func studentsChecker() {
} }
} }
// Check Matrix (only if GLUE Ok and defer contraint) // Check Matrix (only if GLUE Ok and)
if glueErr == nil && istd%10 == check_matrix_for { if glueErr == nil && istd%10 == check_matrix_for {
if v, err := check_matrix(std.MyDelegatedDomain()); err == nil { if v, err := check_matrix(std.MyDelegatedDomain()); err == nil {
if verbose { if verbose {
@ -532,23 +364,6 @@ func studentsChecker() {
} }
} }
} }
// Check DNSSEC (only if GLUE Ok)
if glueErr == nil {
if err := check_dnssec(std.MyDelegatedDomain(), dnsIP); err == nil {
if verbose {
log.Printf("%s just unlocked DNSSEC challenge\n", std.Login)
}
if _, err := std.UnlockChallenge(100*(tunnel_version-1)+7, ""); err != nil {
log.Printf("Unable to register challenge for %s: %s\n", std.Login, err.Error())
}
} else {
std.RegisterChallengeError(100*(tunnel_version-1)+7, err)
if verbose {
log.Printf("%s and DNSSEC: %s\n", std.Login, err)
}
}
}
} }
} else { } else {
if errreg := std.RegisterChallengeError(100*(tunnel_version-1)+3, err); errreg != nil { if errreg := std.RegisterChallengeError(100*(tunnel_version-1)+3, err); errreg != nil {

View File

@ -29,7 +29,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).String()) {
return fmt.Errorf("%q is not your IP range", ip) return fmt.Errorf("%q is not your IP range")
} }
client := dns.Client{Net: "tcp", Timeout: time.Second * 5} client := dns.Client{Net: "tcp", Timeout: time.Second * 5}

View File

@ -205,17 +205,17 @@ func parseZoneRead(globalDomain string, domain string) (rr []Entry, err error) {
for _, r := range response.RR { for _, r := range response.RR {
if strings.HasSuffix(r.Header().Name, domain) { if strings.HasSuffix(r.Header().Name, domain) {
z := []string{} var z string
if v, ok := r.(*dns.A); ok { if v, ok := r.(*dns.A); ok {
z = append(z, fmt.Sprintf("%s", v.A)) z = fmt.Sprintf("%s", v.A)
} else if v, ok := r.(*dns.AAAA); ok { } else if v, ok := r.(*dns.AAAA); ok {
z = append(z, fmt.Sprintf("%s", v.AAAA)) z = fmt.Sprintf("%s", v.AAAA)
} else if v, ok := r.(*dns.NS); ok { } else if v, ok := r.(*dns.NS); ok {
z = append(z, fmt.Sprintf("%s", v.Ns)) z = fmt.Sprintf("%s", v.Ns)
} else if v, ok := r.(*dns.DS); ok { } else if v, ok := r.(*dns.DS); ok {
z = append(z, fmt.Sprintf("%d", v.KeyTag), fmt.Sprintf("%d", v.Algorithm), fmt.Sprintf("%d", v.DigestType), fmt.Sprintf("%s", v.Digest)) z = fmt.Sprintf("%s", v.Digest)
} }
rr = append(rr, Entry{r.Header().Name, r.Header().Ttl, dns.TypeToString[r.Header().Rrtype], "", z}) rr = append(rr, Entry{r.Header().Name, r.Header().Ttl, dns.TypeToString[r.Header().Rrtype], "", []string{z}})
} }
} }
} }
@ -260,7 +260,7 @@ func delAssociatedDomains(student *adlin.Student, dn string) (err error) {
m1.Id = dns.Id() m1.Id = dns.Id()
m1.Opcode = dns.OpcodeUpdate m1.Opcode = dns.OpcodeUpdate
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: adlin.AssociatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m1.Question[0] = dns.Question{adlin.AssociatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
var rrs []dns.RR var rrs []dns.RR
for _, domain := range adomains { for _, domain := range adomains {
@ -302,7 +302,7 @@ func AddAssociatedDomains(student *adlin.Student, aaaa net.IP) (err error) {
m2.Id = dns.Id() m2.Id = dns.Id()
m2.Opcode = dns.OpcodeUpdate m2.Opcode = dns.OpcodeUpdate
m2.Question = make([]dns.Question, 1) m2.Question = make([]dns.Question, 1)
m2.Question[0] = dns.Question{Name: adlin.AssociatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m2.Question[0] = dns.Question{adlin.AssociatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
rrA := new(dns.A) rrA := new(dns.A)
rrA.Hdr = dns.RR_Header{Name: student.DefaultAssociatedDomain(), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 3600} rrA.Hdr = dns.RR_Header{Name: student.DefaultAssociatedDomain(), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 3600}
@ -354,7 +354,7 @@ func AddNSDelegatedDomain(student *adlin.Student, dn string, ttl uint32, ns stri
m1.Id = dns.Id() m1.Id = dns.Id()
m1.Opcode = dns.OpcodeUpdate m1.Opcode = dns.OpcodeUpdate
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m1.Question[0] = dns.Question{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
rrNS := new(dns.NS) rrNS := new(dns.NS)
rrNS.Hdr = dns.RR_Header{Name: d, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: ttl} rrNS.Hdr = dns.RR_Header{Name: d, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: ttl}
@ -377,7 +377,7 @@ func UpdateNSDelegatedDomain(student *adlin.Student, dn string, ttl uint32, oldn
m1.Id = dns.Id() m1.Id = dns.Id()
m1.Opcode = dns.OpcodeUpdate m1.Opcode = dns.OpcodeUpdate
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m1.Question[0] = dns.Question{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
rrOldNS := new(dns.NS) rrOldNS := new(dns.NS)
rrOldNS.Hdr = dns.RR_Header{Name: d, Rrtype: dns.TypeNS, Class: dns.ClassINET} rrOldNS.Hdr = dns.RR_Header{Name: d, Rrtype: dns.TypeNS, Class: dns.ClassINET}
@ -417,7 +417,7 @@ func AddGLUEDelegatedDomain(student *adlin.Student, dn string, ttl uint32, aaaa
m1.Id = dns.Id() m1.Id = dns.Id()
m1.Opcode = dns.OpcodeUpdate m1.Opcode = dns.OpcodeUpdate
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m1.Question[0] = dns.Question{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
var rr dns.RR var rr dns.RR
rr, err = dns.NewRR(fmt.Sprintf("%s %d IN AAAA %s", dn, ttl, aaaa)) rr, err = dns.NewRR(fmt.Sprintf("%s %d IN AAAA %s", dn, ttl, aaaa))
@ -453,7 +453,7 @@ func UpdateGLUEDelegatedDomain(student *adlin.Student, dn string, ttl uint32, ol
m1.Id = dns.Id() m1.Id = dns.Id()
m1.Opcode = dns.OpcodeUpdate m1.Opcode = dns.OpcodeUpdate
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m1.Question[0] = dns.Question{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
var rr dns.RR var rr dns.RR
@ -509,7 +509,7 @@ func AddDSDelegatedDomain(student *adlin.Student, dn string, ttl uint32, rdata s
m1.Id = dns.Id() m1.Id = dns.Id()
m1.Opcode = dns.OpcodeUpdate m1.Opcode = dns.OpcodeUpdate
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m1.Question[0] = dns.Question{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
var ds *dns.DS var ds *dns.DS
ds = dnskey.ToDS(dns.SHA256) ds = dnskey.ToDS(dns.SHA256)
@ -545,7 +545,7 @@ func DeleteRRDelegatedDomain(student *adlin.Student, dn string, rr string, value
m1.Id = dns.Id() m1.Id = dns.Id()
m1.Opcode = dns.OpcodeUpdate m1.Opcode = dns.OpcodeUpdate
m1.Question = make([]dns.Question, 1) m1.Question = make([]dns.Question, 1)
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: dns.ClassINET} m1.Question[0] = dns.Question{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
rrr, errr := dns.NewRR(fmt.Sprintf("%s %s %s", dn, rr, strings.Join(values, " "))) rrr, errr := dns.NewRR(fmt.Sprintf("%s %s %s", dn, rr, strings.Join(values, " ")))
if errr != nil { if errr != nil {

View File

@ -104,11 +104,11 @@
</div> </div>
</div> </div>
<div class="d-flex flex-wrap justify-content-around" style="padding: 0"> <div class="d-flex flex-wrap justify-content-around" style="padding: 0">
<span class="badge" ng-repeat="(ch,t) in tuto_progress[tutoid]" ng-class="{'badge-success': stats[ch].success > 0 || (tutoid == 0 && stats[ch].warning > 0), 'badge-warning': tutoid != 0 && stats[ch].success == 0 && stats[ch].warning > 0, 'badge-danger': !stats[ch] || (stats[ch].success == 0 && stats[ch].warning == 0)}" title="{{ t.title }}: {{ stats[ch].success }} - {{ stats[ch].warning }}/{{ stats.total }}" ng-click="toogleBadge(ch)" ng-cloak>{{ stats[ch].warning * 100 / stats.total | number:0 }} %</span> <span class="badge" ng-repeat="(ch,t) in tuto_progress[tutoid]" ng-class="{'badge-success': stats[ch].success > 0 || (tutoid == 0 && stats[ch].warning > 0), 'badge-warning': tutoid != 0 && stats[ch].success == 0 && stats[ch].warning > 0, 'badge-danger': !stats[ch] || (stats[ch].success == 0 && stats[ch].warning == 0)}" title="{{ t.title }}: {{ stats[ch].success }} - {{ stats[ch].warning }}/{{ stats.total }}" ng-cloak>{{ stats[ch].warning * 100 / stats.total | number:0 }} %</span>
</div> </div>
</div> </div>
<div class="card student d-flex flex-column justify-content-between" ng-repeat="(login, mychallenges) in students" ng-if="login != 'nemunaire'" style="background-image: url('https://photos.cri.epita.fr/square/{{ mychallenges.img | lowercase }}')" ng-show="!filterBadgeState.challenge || (filterBadgeState.state == 'bad' && (!mychallenges[filterBadgeState.challenge] || !mychallenges[filterBadgeState.challenge].recent)) || (filterBadgeState.state == 'passed' && mychallenges[filterBadgeState.challenge] && mychallenges[filterBadgeState.challenge].recent) || (filterBadgeState.state == 'online' && mychallenges[filterBadgeState.challenge] && mychallenges[filterBadgeState.challenge].recent <= 300) || (filterBadgeState.state == 'offline' && mychallenges[filterBadgeState.challenge] && mychallenges[filterBadgeState.challenge].recent > 300)"> <div class="card student d-flex flex-column justify-content-between" ng-repeat="(login, mychallenges) in students" ng-if="login != 'nemunaire'" style="background-image: url('https://photos.cri.epita.fr/square/{{ mychallenges.img | lowercase }}')">
<h5 class="login text-truncate" title="{{ login }}"> <h5 class="login text-truncate" title="{{ login }}">
<span class="badge" ng-class="{'badge-success': mychallenges['ping'] && mychallenges['ping'].recent < 120, 'badge-info': mychallenges['ping'] && mychallenges['ping'].recent >= 120 && mychallenges['ping'].recent < 300, 'badge-warning': mychallenges['ping'] && mychallenges['ping'].recent >= 300 && mychallenges['ping'].recent < 900, 'badge-danger': mychallenges['ping'] && mychallenges['ping'].recent >= 900, 'badge-dark': !mychallenges['ping']}" title="{{ mychallenges['ping'].time }}"> <span class="badge" ng-class="{'badge-success': mychallenges['ping'] && mychallenges['ping'].recent < 120, 'badge-info': mychallenges['ping'] && mychallenges['ping'].recent >= 120 && mychallenges['ping'].recent < 300, 'badge-warning': mychallenges['ping'] && mychallenges['ping'].recent >= 300 && mychallenges['ping'].recent < 900, 'badge-danger': mychallenges['ping'] && mychallenges['ping'].recent >= 900, 'badge-dark': !mychallenges['ping']}" title="{{ mychallenges['ping'].time }}">
&#x1f4bb; &#x1f4bb;

View File

@ -43,28 +43,6 @@ angular.module("AdLinApp")
$scope.tuto_progress = tuto_progress; $scope.tuto_progress = tuto_progress;
$scope.stats = {}; $scope.stats = {};
$scope.students = {}; $scope.students = {};
$scope.filterBadgeState = {};
$scope.toogleBadge = function(ch) {
if ($scope.filterBadgeState["challenge"] && $scope.filterBadgeState["challenge"] == ch) {
switch ($scope.filterBadgeState["state"]) {
case "bad":
$scope.filterBadgeState["state"] = "passed";
break;
case "passed":
$scope.filterBadgeState["state"] = "online";
break;
case "online":
$scope.filterBadgeState["state"] = "offline";
break;
default:
$scope.filterBadgeState = {};
}
} else {
$scope.filterBadgeState["challenge"] = ch;
$scope.filterBadgeState["state"] = "bad";
}
};
var refreshStd = function() { var refreshStd = function() {
var students = Progression.get(); var students = Progression.get();

View File

@ -312,11 +312,9 @@ angular.module("AdLinApp")
method: 'GET', method: 'GET',
url: "api/adomains/" + domain, url: "api/adomains/" + domain,
}).then(function(response) { }).then(function(response) {
if (response.data) {
response.data.forEach(function(rr) { response.data.forEach(function(rr) {
$scope.adomains.push(rr); $scope.adomains.push(rr);
}); });
}
}); });
}, function(response) { }, function(response) {
console.log(response.data.errmsg); console.log(response.data.errmsg);
@ -544,8 +542,8 @@ angular.module("AdLinApp")
$scope.nsrr = { $scope.nsrr = {
"domain": domain, "domain": domain,
"ttl": 900, "ttl": 900,
"rr": "DNSKEY", "rr": "DS",
"labels": ["Flags", "Protocole", "Algorithme", "Clef publique (base64)"], "labels": ["Key Tag", "Flag", "Algorithme", "Clef publique (base64)"],
"values": ["", "", "", ""], "values": ["", "", "", ""],
} }
$('#NSModal').modal('show'); $('#NSModal').modal('show');
@ -555,7 +553,7 @@ angular.module("AdLinApp")
"domain": domain, "domain": domain,
"ttl": rr.ttl, "ttl": rr.ttl,
"rr": "DS", "rr": "DS",
"labels": ["Key Tag", "Algo clef", "Type de hash", "Hash (hex)"], "labels": ["Key Tag", "Algo clef", "Algo hash", "Hash (hex)"],
"valuesfrom": rr.values.join(" "), "valuesfrom": rr.values.join(" "),
"values": rr.values, "values": rr.values,
} }
@ -565,8 +563,6 @@ angular.module("AdLinApp")
$scope.saveNSRR = function(nsrr) { $scope.saveNSRR = function(nsrr) {
if (nsrr.ttl) if (nsrr.ttl)
nsrr.ttl = parseInt(nsrr.ttl) nsrr.ttl = parseInt(nsrr.ttl)
if (nsrr.rr == "DNSKEY")
nsrr.rr = "DS"
$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

@ -31,8 +31,8 @@
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" ng-show="pleaseWaitNewAssociation"></span> <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" ng-show="pleaseWaitNewAssociation"></span>
Demander une nouvelle association Demander une nouvelle association
</button> </button>
<button class="btn ml-2" ng-class="{'btn-secondary': !adomains || !adomains.length, 'btn-success': adomains && adomains.length}" ng-disabled="!adomains || !adomains.length" title="Si tu disposes de ton propre domaine chez un véritable hébergeur, tu peux dédier un sous-domaine pour l'utiliser à la place du domaine qui t'es proposé par Maatma." ng-click="useMyAssociationD()"> <button class="btn ml-2" ng-class="{'btn-secondary': !adomains || !adomains.length, 'btn-success': adomains && adomains.length}" ng-disabled="!adomains || !adomains.length" ng-click="useMyAssociationD()">
Utiliser mon propre domaine Utiliser mon domaine
</button> </button>
</td> </td>
</tr> </tr>
@ -63,9 +63,9 @@
<div ng-repeat="domain in ddomains"> <div ng-repeat="domain in ddomains">
<h4 class="text-muted"> <h4 class="text-muted">
{{ domain }} {{ domain }}
<button class="btn btn-sm btn-info ml-2" ng-if="$first" title="Si tu disposes de ton propre domaine chez un véritable hébergeur, tu peux dédier un sous-domaine pour l'utiliser à la place du domaine qui t'es proposé par Maatma." ng-click="useMyDelegationD()"> <button class="btn btn-sm btn-info ml-2" ng-if="$first" ng-click="useMyDelegationD()">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" ng-show="pleaseWaitNewDelegation"></span> <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" ng-show="pleaseWaitNewDelegation"></span>
Utiliser mon propre domaine Utiliser mon domaine
</button> </button>
</h4> </h4>
@ -169,7 +169,7 @@
</thead> </thead>
<tbody style="font-family: monospace" ng-if="domainDS"> <tbody style="font-family: monospace" ng-if="domainDS">
<tr ng-repeat="rr in domainDS"> <tr ng-repeat="rr in domainDS">
<td ng-repeat="val in rr.values track by $index">{{ val }}</td> <td ng-repeat="val in rr.values">{{ val }}</td>
<td> <td>
<button class="btn btn-danger" ng-click="deleteRR(domain, rr)"> <button class="btn btn-danger" ng-click="deleteRR(domain, rr)">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" ng-show="rr.pleaseWaitDSdel"></span> <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" ng-show="rr.pleaseWaitDSdel"></span>
@ -324,7 +324,7 @@ ns.{{ student.delegated_domain }} 300 IN AAAA [your NS ip]
</div> </div>
</form> </form>
<p> <p>
Ensuite, configure ta zone DNS, pour réaliser la délégation. L'interface de maatma ne te sera plus utile, car pour réaliser la délégation, tu dois passer par l'interface du bureau d'enregistrement de ton domaine. Ensuite, configure ta zone DNS, pour réaliser la délégation. L'interface
</p> </p>
<pre> <pre>
;; Delegation {{ assoc.ns }} to the given name server ;; Delegation {{ assoc.ns }} to the given name server
@ -349,7 +349,6 @@ ns.{{ assoc.ns }} 300 IN AAAA [your NS ip]
<h5 class="modal-title" ng-if="nsrr.rr == 'NS'">Modifier la liste des serveurs de noms de la zone</h5> <h5 class="modal-title" ng-if="nsrr.rr == 'NS'">Modifier la liste des serveurs de noms de la zone</h5>
<h5 class="modal-title" ng-if="nsrr.rr == 'AAAA'">Modifier les enregistrements GLUE du domaine</h5> <h5 class="modal-title" ng-if="nsrr.rr == 'AAAA'">Modifier les enregistrements GLUE du domaine</h5>
<h5 class="modal-title" ng-if="nsrr.rr == 'DS'">Modifier les clefs DNSSEC de la zone parente</h5> <h5 class="modal-title" ng-if="nsrr.rr == 'DS'">Modifier les clefs DNSSEC de la zone parente</h5>
<h5 class="modal-title" ng-if="nsrr.rr == 'DNSKEY'">Ajout d'un enregistrement DS (à partir d'un enregistrement DNSKEY)</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
@ -359,7 +358,7 @@ ns.{{ assoc.ns }} 300 IN AAAA [your NS ip]
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-2 col-form-label">Domaine</label> <label class="col-sm-2 col-form-label">Domaine</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input class="form-control-plaintext" ng-model="nsrr.domain" ng-if="nsrr.rr == 'NS' || nsrr.rr == 'DS' || nsrr.rr == 'DNSKEY'" readonly> <input class="form-control-plaintext" ng-model="nsrr.domain" ng-if="nsrr.rr == 'NS' || nsrr.rr == 'DS'" readonly>
<input class="form-control" ng-model="nsrr.domain" ng-if="nsrr.rr == 'AAAA'"> <input class="form-control" ng-model="nsrr.domain" ng-if="nsrr.rr == 'AAAA'">
</div> </div>
</div> </div>

View File

@ -69,9 +69,9 @@ func GetStudentTunnelIPs(student *adlin.Student) (ips []string) {
func getStudentIPs(student *adlin.Student) (r map[string]string) { func getStudentIPs(student *adlin.Student) (r map[string]string) {
r = make(map[string]string) r = make(map[string]string)
r["vlan0"] = IPSuffix(student, net.IPNet{IP: net.ParseIP("172.23.0.0"), Mask: net.CIDRMask(17, 32)}).String() r["vlan0"] = IPSuffix(student, net.IPNet{net.ParseIP("172.23.0.0"), net.CIDRMask(17, 32)}).String()
r["wg0"] = IPSuffix(student, net.IPNet{IP: net.ParseIP("172.17.0.0"), Mask: net.CIDRMask(16, 32)}).String() r["wg0"] = IPSuffix(student, net.IPNet{net.ParseIP("172.17.0.0"), net.CIDRMask(16, 32)}).String()
r["vlan7"] = IPSuffix(student, net.IPNet{IP: net.ParseIP("172.23.142.0"), Mask: net.CIDRMask(23, 32)}).String() r["vlan7"] = IPSuffix(student, net.IPNet{net.ParseIP("172.23.142.0"), net.CIDRMask(23, 32)}).String()
for d, ip := range GetStudentTunnelIPs(student) { for d, ip := range GetStudentTunnelIPs(student) {
key := "wg" key := "wg"

View File

@ -104,7 +104,7 @@ func createStudent(_ httprouter.Params, body []byte) (interface{}, error) {
} }
exist.RegisterAccess(std.IP, std.MAC) exist.RegisterAccess(std.IP, std.MAC)
ip := IPSuffix(exist, net.IPNet{IP: net.ParseIP("172.23.0.0"), Mask: net.CIDRMask(17, 32)}).String() ip := IPSuffix(exist, net.IPNet{net.ParseIP("172.23.0.0"), net.CIDRMask(17, 32)}).String()
exist.IP = &ip exist.IP = &ip
return exist, nil return exist, nil

View File

@ -111,7 +111,7 @@ func getWgTunnelInfo(w http.ResponseWriter, r *http.Request, ps httprouter.Param
pt.PubKey, _ = base64.StdEncoding.DecodeString(pubkey) pt.PubKey, _ = base64.StdEncoding.DecodeString(pubkey)
version = 3 version = 3
} else { } else {
http.Error(w, fmt.Sprintf("{errmsg:\"No public key given\"}"), http.StatusBadRequest) http.Error(w, fmt.Sprintf("{errmsg:\"No public key given\"}", err), http.StatusBadRequest)
return return
} }

View File

@ -69,11 +69,3 @@ avoir à connaître son IP.
Dans un deuxième temps, nous verrons comment tirer parti de la délégation. Vous Dans un deuxième temps, nous verrons comment tirer parti de la délégation. Vous
pouvez l'ignorer pour le moment. pouvez l'ignorer pour le moment.
Notez que vous ne disposez pas d'IPv4 publique (c'est à dire routable sur
Internet), vous disposez seulement d'une IPv6 publique. L'ensemble de vos
services sont cependant accessibles également en IPv4, car Maatma centralise
les requêtes faites en IPv4 et les distribue entre vos IPv6, lorsque le
protocole permet de faire cette distribution. Par exemple, HTTP et HTTPS le
permette, mais pas SSH. Vous ne pourrez donc pas vous connecter en SSH via
l'IPv4 de Maatma.

View File

@ -16,7 +16,7 @@ Voici les grandes étapes :
* tester avec `dig @votreIPv4locale ANY login-x.srs.p0m.fr` que votre serveur réagit bien correctement ; * tester avec `dig @votreIPv4locale ANY login-x.srs.p0m.fr` que votre serveur réagit bien correctement ;
* publier sur Maatma le nom de domaine où votre serveur de nom est joignable (généralement `ns.login-x.srs.p0m.fr`), il s'agit d'un enregistrement `NS` ; * publier sur Maatma le nom de domaine où votre serveur de nom est joignable (généralement `ns.login-x.srs.p0m.fr`), il s'agit d'un enregistrement `NS` ;
* publier également sa *GLUE*, afin de résoudre le problème de poule et d'œuf (le domaine de votre serveur de noms étant dans la zone qu'il est sensé servir, le bureau d'enregistrement enverra également l'IP correspondant au domaine) ; * publier également sa *GLUE*, afin de résoudre le problème de poule et d'œuf (le domaine de votre serveur de noms étant dans la zone qu'il est sensé servir, le bureau d'enregistrement enverra également l'IP correspondant au domaine) ;
* tester avec `dig @9.9.9.9 AAAA login-x.srs.p0m.fr` que votre serveur est bien joignable. * tester avec `dig @9.9.9.9 ANY login-x.srs.p0m.fr` que votre serveur est bien joignable.
Un ouvrage de référence, qui répondra à l'intégralité de vos questions et manières d'utiliser votre serveur DNS se trouve à <http://www.zytrax.com/books/dns/>. Un ouvrage de référence, qui répondra à l'intégralité de vos questions et manières d'utiliser votre serveur DNS se trouve à <http://www.zytrax.com/books/dns/>.
@ -139,22 +139,6 @@ Ce sont les administrateurs de la zone `wikipedia.org.` qui ont indiqué à
domaine votre serveur de noms, ainsi que le *GLUE record* qui lui correspond. domaine votre serveur de noms, ainsi que le *GLUE record* qui lui correspond.
## À propos de Maatma et du portail IPv4
Maatma met à votre disposition une plage d'IPv6 publique, directement
routable sur Internet. Mais aujourd'hui encore, de nombreuses
installation ne disposent pas de ce protocole de communication et ne
peuvent accéder aux machines connectées en IPv4 seulement.
Pour palier cela, Maatma met à votre disposition une IPv4 mutualisée
entre tous les SRS. Un service écoute sur la machine au bout de cette
IP, afin de distribuer le trafic entre vous, selon la demande du
client. Tous les protocoles ne permettent pas d'identifier le domaine
de destination, donc ce sont les protocoles HTTP et HTTPS qui sont
transmis sur vos IPv6.
## DNSSEC (bonus) ## DNSSEC (bonus)
En bonus, vous devriez sécuriser les réponses envoyées par votre serveur DNS. En bonus, vous devriez sécuriser les réponses envoyées par votre serveur DNS.