Compare commits
8 Commits
caaa30c747
...
a52bf0e52d
Author | SHA1 | Date | |
---|---|---|---|
a52bf0e52d | |||
2f13023128 | |||
b73cab920a | |||
78e7da799a | |||
fbaad50fbd | |||
eab1af36f4 | |||
5d0693180d | |||
cd6a63fc57 |
@ -19,6 +19,7 @@ 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
|
||||||
@ -88,9 +89,11 @@ 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 {
|
||||||
@ -102,6 +105,168 @@ 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) {
|
||||||
@ -170,6 +335,7 @@ 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 {
|
||||||
@ -187,7 +353,7 @@ type matrix_result struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
FederationOK bool
|
FederationOK bool `json:"FederationOK"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func check_matrix(domain string) (version string, err error) {
|
func check_matrix(domain string) (version string, err error) {
|
||||||
@ -199,16 +365,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", domain)
|
return "", fmt.Errorf("Sorry, the federation tester is broken. Check on https://federationtester.matrix.org/#%s", strings.TrimSuffix(domain, "."))
|
||||||
}
|
}
|
||||||
|
|
||||||
var federationTest matrix_result
|
var federationTest matrix_result
|
||||||
if federationTest.FederationOK {
|
if err = json.NewDecoder(resp.Body).Decode(&federationTest); err != nil {
|
||||||
|
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 {
|
||||||
@ -222,8 +388,10 @@ 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", 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", strings.TrimSuffix(domain, "."))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +516,7 @@ func studentsChecker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check Matrix (only if GLUE Ok and)
|
// Check Matrix (only if GLUE Ok and defer contraint)
|
||||||
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 {
|
||||||
@ -364,6 +532,23 @@ 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 {
|
||||||
|
@ -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")
|
return fmt.Errorf("%q is not your IP range", ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
client := dns.Client{Net: "tcp", Timeout: time.Second * 5}
|
client := dns.Client{Net: "tcp", Timeout: time.Second * 5}
|
||||||
|
@ -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) {
|
||||||
var z string
|
z := []string{}
|
||||||
if v, ok := r.(*dns.A); ok {
|
if v, ok := r.(*dns.A); ok {
|
||||||
z = fmt.Sprintf("%s", v.A)
|
z = append(z, fmt.Sprintf("%s", v.A))
|
||||||
} else if v, ok := r.(*dns.AAAA); ok {
|
} else if v, ok := r.(*dns.AAAA); ok {
|
||||||
z = fmt.Sprintf("%s", v.AAAA)
|
z = append(z, fmt.Sprintf("%s", v.AAAA))
|
||||||
} else if v, ok := r.(*dns.NS); ok {
|
} else if v, ok := r.(*dns.NS); ok {
|
||||||
z = fmt.Sprintf("%s", v.Ns)
|
z = append(z, fmt.Sprintf("%s", v.Ns))
|
||||||
} else if v, ok := r.(*dns.DS); ok {
|
} else if v, ok := r.(*dns.DS); ok {
|
||||||
z = fmt.Sprintf("%s", v.Digest)
|
z = append(z, fmt.Sprintf("%d", v.KeyTag), fmt.Sprintf("%d", v.Algorithm), fmt.Sprintf("%d", v.DigestType), fmt.Sprintf("%s", v.Digest))
|
||||||
}
|
}
|
||||||
rr = append(rr, Entry{r.Header().Name, r.Header().Ttl, dns.TypeToString[r.Header().Rrtype], "", []string{z}})
|
rr = append(rr, Entry{r.Header().Name, r.Header().Ttl, dns.TypeToString[r.Header().Rrtype], "", 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{adlin.AssociatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m1.Question[0] = dns.Question{Name: adlin.AssociatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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{adlin.AssociatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m2.Question[0] = dns.Question{Name: adlin.AssociatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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{adlin.DelegatedDomainSuffix, dns.TypeSOA, dns.ClassINET}
|
m1.Question[0] = dns.Question{Name: adlin.DelegatedDomainSuffix, Qtype: dns.TypeSOA, Qclass: 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 {
|
||||||
|
@ -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-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-click="toogleBadge(ch)" 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 }}')">
|
<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)">
|
||||||
<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 }}">
|
||||||
💻
|
💻
|
||||||
|
@ -43,6 +43,28 @@ 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();
|
||||||
|
@ -312,9 +312,11 @@ 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);
|
||||||
@ -542,8 +544,8 @@ angular.module("AdLinApp")
|
|||||||
$scope.nsrr = {
|
$scope.nsrr = {
|
||||||
"domain": domain,
|
"domain": domain,
|
||||||
"ttl": 900,
|
"ttl": 900,
|
||||||
"rr": "DS",
|
"rr": "DNSKEY",
|
||||||
"labels": ["Key Tag", "Flag", "Algorithme", "Clef publique (base64)"],
|
"labels": ["Flags", "Protocole", "Algorithme", "Clef publique (base64)"],
|
||||||
"values": ["", "", "", ""],
|
"values": ["", "", "", ""],
|
||||||
}
|
}
|
||||||
$('#NSModal').modal('show');
|
$('#NSModal').modal('show');
|
||||||
@ -553,7 +555,7 @@ angular.module("AdLinApp")
|
|||||||
"domain": domain,
|
"domain": domain,
|
||||||
"ttl": rr.ttl,
|
"ttl": rr.ttl,
|
||||||
"rr": "DS",
|
"rr": "DS",
|
||||||
"labels": ["Key Tag", "Algo clef", "Algo hash", "Hash (hex)"],
|
"labels": ["Key Tag", "Algo clef", "Type de hash", "Hash (hex)"],
|
||||||
"valuesfrom": rr.values.join(" "),
|
"valuesfrom": rr.values.join(" "),
|
||||||
"values": rr.values,
|
"values": rr.values,
|
||||||
}
|
}
|
||||||
@ -563,6 +565,8 @@ 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,
|
||||||
|
@ -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" 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" 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()">
|
||||||
Utiliser mon domaine
|
Utiliser mon propre 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" ng-click="useMyDelegationD()">
|
<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()">
|
||||||
<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 domaine
|
Utiliser mon propre 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">{{ val }}</td>
|
<td ng-repeat="val in rr.values track by $index">{{ 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
|
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.
|
||||||
</p>
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
;; Delegation {{ assoc.ns }} to the given name server
|
;; Delegation {{ assoc.ns }} to the given name server
|
||||||
@ -349,6 +349,7 @@ 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">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
@ -358,7 +359,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'" readonly>
|
<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" 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>
|
||||||
|
@ -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{net.ParseIP("172.23.0.0"), net.CIDRMask(17, 32)}).String()
|
r["vlan0"] = IPSuffix(student, net.IPNet{IP: net.ParseIP("172.23.0.0"), Mask: net.CIDRMask(17, 32)}).String()
|
||||||
r["wg0"] = IPSuffix(student, net.IPNet{net.ParseIP("172.17.0.0"), net.CIDRMask(16, 32)}).String()
|
r["wg0"] = IPSuffix(student, net.IPNet{IP: net.ParseIP("172.17.0.0"), Mask: net.CIDRMask(16, 32)}).String()
|
||||||
r["vlan7"] = IPSuffix(student, net.IPNet{net.ParseIP("172.23.142.0"), net.CIDRMask(23, 32)}).String()
|
r["vlan7"] = IPSuffix(student, net.IPNet{IP: net.ParseIP("172.23.142.0"), Mask: net.CIDRMask(23, 32)}).String()
|
||||||
|
|
||||||
for d, ip := range GetStudentTunnelIPs(student) {
|
for d, ip := range GetStudentTunnelIPs(student) {
|
||||||
key := "wg"
|
key := "wg"
|
||||||
|
@ -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{net.ParseIP("172.23.0.0"), net.CIDRMask(17, 32)}).String()
|
ip := IPSuffix(exist, net.IPNet{IP: net.ParseIP("172.23.0.0"), Mask: net.CIDRMask(17, 32)}).String()
|
||||||
exist.IP = &ip
|
exist.IP = &ip
|
||||||
|
|
||||||
return exist, nil
|
return exist, nil
|
||||||
|
@ -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\"}", err), http.StatusBadRequest)
|
http.Error(w, fmt.Sprintf("{errmsg:\"No public key given\"}"), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,3 +69,11 @@ 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.
|
||||||
|
@ -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 ANY login-x.srs.p0m.fr` que votre serveur est bien joignable.
|
* tester avec `dig @9.9.9.9 AAAA 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,6 +139,22 @@ 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.
|
||||||
|
Reference in New Issue
Block a user