This shows you the differences between two versions of the page.
|
pc:laboratoare:11 [2022/05/14 02:39] bogdan_costel.mocanu [Protocolul DNS] |
pc:laboratoare:11 [2023/05/07 17:56] (current) dorinel.filip [Exerciții] New domain |
||
|---|---|---|---|
| Line 39: | Line 39: | ||
| - | ==== Structura mesajelor e-mail ==== | + | ==== Protocolul DNS ==== |
| + | |||
| + | DNS folosește în general protocolul UDP pe portul 53, dar, în cazul răspunsurilor de dimensiuni mai mari sau pentru operații ca transferul de zone, se utilizează și TCP. Mai recent, s-a introdus și DNS over HTTPS (sau DoH, descris în RFC [[https://tools.ietf.org/html/rfc8484|8484]]), care presupune realizarea de cereri DNS peste HTTPS din motive de securitate. | ||
| + | |||
| + | === Spațiul de nume === | ||
| + | |||
| + | DNS organizează numele resurselor într-o ierarhie de domenii. Un domeniu reprezintă o colecție de sisteme gazdă care au unele proprietăți în comun, cum ar fi faptul că toate aparțin unei aceleiași organizații sau faptul că toate sunt situate geografic în același perimetru. | ||
| + | |||
| + | {{:pc:laboratoare:dns.gif?400|}} | ||
| + | |||
| + | Fiecare domeniu este partiționat în subdomenii și acestea sunt la rândul lor, partiționate, ș.a.m.d. Toate aceste domenii pot fi reprezentate ca un arbore, după cum se poate vedea mai sus. Frunzele arborelui reprezintă domenii care nu au subdomenii, dar care conțin totuși sisteme. Un domeniu frunză poate conține de la un singur sistem gazdă până la mii de sisteme gazdă. | ||
| + | |||
| + | Domeniile de pe primul nivel se împart în două categorii: generice (gTLD-uri) și de țări (ccTLD-uri). Domeniile generice inițiale erau //com// (comercial), //edu// (instituții educaționale), //gov// (guvernul SUA), //int// (organizații internaționale), //mil// (forțele armate ale SUA) și //org// (organizații nonprofit). În ziua de astăzi, restricțiile legate de astfel de domenii sunt mult mai mici, existând astfel peste 1200 de domenii top-level generice. Domeniile de țări includ o intrare pentru fiecare țară, după cum se definește în ISO [[https://www.iso.org/iso-3166-country-codes.html|3166]]. Fiecare domeniu este denumit de calea în arbore până la rădăcină. Componentele sunt separate prin punct. Astfel, departamentul de Calculatoare de la UPB poate fi //cs.pub.ro// în loc de numele în stil UNIX ///ro/pub/cs//. | ||
| + | |||
| + | Numele de domenii pot fi absolute sau relative. Un nume absolut de domeniu (FQDN - fully qualified domain name) este un nume de domeniu care nu permite nici o ambiguitate cu privire la locația relativă la rădăcina arborelui de nume de domenii. Astfel de nume absolute de domenii se termină cu punct (de exemplu //cs.pub.ro.//). În contrast, un nume relativ de domeniu este un nume care are sens numai relativ la un anume domeniu DNS (altul decât cel rădăcină). | ||
| + | |||
| + | Numele de domenii nu fac distincție între litere mici și litere mari, //edu// sau //EDU// însemnând practic același lucru. Componentele numelor pot avea o lungime de cel mult 64 de caractere, iar întreaga cale de nume nu trebuie să depășească 255 de caractere. | ||
| + | |||
| + | Fiecare domeniu controlează cum sunt alocate domeniile de sub el. De exemplu, Japonia are domeniile //ac.jp// și //co.jp// echivalente cu //edu// și //com//. Olanda nu face nicio distincție și pune toate organizațiile direct sub //nl//. Pentru a crea un nou domeniu, se cere permisiunea domeniului în care va fi inclus. De exemplu, dacă un grup PCom de la CS dorește să fie cunoscut ca //pcom.cs.pub.ro//, acesta are nevoie de permisiunea celui care administrează //cs.pub.ro//. Similar, o nouă universitate care dorește obținerea unui domeniu va trebui să ceară permisiunea administratorului domeniului //edu//. În acest mod, sunt evitate conflictele de nume și fiecare domeniu poate ține evidența tuturor subdomeniilor sale. Odată ce un nou domeniu a fost creat și înregistrat, el poate crea subdomenii, fără a cere permisiune de la cineva din partea superioară a arborelui. | ||
| + | |||
| + | === Algoritmul de interogare === | ||
| + | |||
| + | Conceptele cu care DNS lucrează sunt: | ||
| + | - Servere DNS - Stații care rulează programe de tip server de DNS ce conțin informații asupra bazelor de date DNS și despre structura numelor de domenii. | ||
| + | - Resolvere DNS - Programe care folosesc cereri DNS pentru interogarea unor servere DNS. Modul în care se derulează procesul de interogare DNS este cel din figura de mai jos. | ||
| + | |||
| + | {{:pc:laboratoare:understanding-dns-queries-and-lookups.jpg?600|}} | ||
| + | |||
| + | === Înregistrări de resurse === | ||
| + | |||
| + | Fiecărui domeniu, fie că este un singur calculator gazdă, fie un domeniu de nivel superior, îi poate fi asociată o mulțime de înregistrări de resurse (resource records sau RR-uri). Pentru un singur sistem gazdă, cea mai obișnuită înregistrare de resursă este chiar adresa IP, dar există multe alte tipuri. | ||
| + | |||
| + | Atunci când procedura resolver trimite un nume de domeniu DNS, ceea ce va primi ca răspuns sunt înregistrările de resurse asociate acelui nume. Astfel, adevărata funcție a DNS este să realizeze corespondența dintre numele de domenii și înregistrări de resurse. | ||
| + | |||
| + | O înregistrare de resursă este un 5-tuplu. Cu toate că, din rațiuni de eficiență, înregistrările de resurse sunt codificate binar, în majoritatea expunerilor ele sunt prezentate ca text ASCII, câte o înregistrare de resurse pe linie. Formatul utilizat este //<Nume_domeniu, Timp_de_viață, Tip, Clasă, Valoare>//: | ||
| + | |||
| + | * Câmpul //Nume_domeniu// precizează domeniul căruia i se aplică această înregistrare. În mod normal, există mai multe înregistrări pentru fiecare domeniu, și fiecare copie a bazei de date păstrează informații despre mai multe domenii. Acest câmp este utilizat cu rol de cheie de căutare primară pentru a satisface cererile. Ordinea înregistrărilor în baza de date nu este semnificativă. Când se face o interogare despre un domeniu, sunt returnate toate înregistrările care se potrivesc cu clasa cerută. | ||
| + | * Câmpul //Timp_de_viață// dă o indicație despre cât de stabilă este înregistrarea. | ||
| + | * Câmpul //Tip// precizează tipul înregistrării. Cele mai importante tipuri sunt prezentate în tabelul de mai jos. | ||
| + | |||
| + | ^ Tip ^ Semnificație ^ Valoare ^ | ||
| + | | SOA | Start autoritate | Parametri pentru această zonă | | ||
| + | | A | Adresa IPv4 a unui sistem gazdă | Întreg pe 32 de biți | | ||
| + | | AAAA | Adresa IPv6 a unui sistem gazdă | Întreg pe 128 de biți | | ||
| + | | MX | Schimb de poștă | Prioritate, domeniu dispus să accepte poștă electronică | | ||
| + | | NS | Server de nume | Numele serverului pentru acest domeniu | | ||
| + | | CNAME | Nume canonic | Numele domeniului | | ||
| + | | PTR | Pointer | Pseudonim pentru adresă IP | | ||
| + | | HINFO | Descriere sistem gazdă | Unitate centrală și sistem de operare în ASCII | | ||
| + | | TXT | Text | Text ASCII neinterpretat | | ||
| + | |||
| + | O înregistrare SOA furnizează numele sursei primare de informație despre zona serverului de nume, adresa de e-mail a administratorului, un identificator unic si diverși indicatori și contoare de timp. | ||
| + | |||
| + | Cel mai important tip de înregistrare este înregistrarea A (adresă). Ea păstrează adresa IP de 32 de biți a sistemului gazdă. Următoarea ca importanță este înregistrarea MX. Aceasta precizează numele domeniului pregătit să accepte poștă electronică pentru domeniul specificat. Înregistrările specifică numele serverului. Un exemplu de informație ce se poate găsi în baza de date DNS a unui domeniu este următorul: | ||
| + | |||
| + | <code> | ||
| + | ; Authoritative Information on physics.groucho.edu. | ||
| + | @ IN SOA niels.physics.groucho.edu. | ||
| + | janet.niels.physics.groucho.edu. { | ||
| + | 1999090200 ; serial no | ||
| + | 360000 ; refresh | ||
| + | 3600 ; retry | ||
| + | 3600000 ; expire | ||
| + | 3600 ; default ttl | ||
| + | }; | ||
| + | ; Name servers | ||
| + | IN NS niels | ||
| + | IN NS gauss.maths.groucho.edu. | ||
| + | gauss.maths.groucho.edu. IN A 149.76.4.23 | ||
| + | ; | ||
| + | ; Theoretical Physics (subnet 12) | ||
| + | niels IN A 149.76.12.1 | ||
| + | IN A 149.76.1.12 | ||
| + | name server IN CNAME niels | ||
| + | otto IN A 149.76.12.2 | ||
| + | quark IN A 149.76.12.4 | ||
| + | down IN A 149.76.12.5 | ||
| + | strange IN A 149.76.12.6 | ||
| + | ... | ||
| + | ; Collider Lab. (subnet 14) | ||
| + | boson IN A 149.76.14.1 | ||
| + | muon IN A 149.76.14.7 | ||
| + | bogon IN A 149.76.14.12 | ||
| + | ... | ||
| + | </code> | ||
| + | |||
| + | === Servere de nume === | ||
| + | |||
| + | Teoretic, un singur server de nume poate conține întreaga bază de date DNS și poate să răspundă tuturor cererilor. În practică, acest server poate fi atât de încărcat încât să devina de neutilizat. Pentru a evita probleme asociate cu existența unei singure surse de informație, spațiul de nume DNS este împărțit în zone care nu se suprapun. O posibilă astfel de împărțire este cea de mai jos. | ||
| + | |||
| + | {{:pc:laboratoare:setup-a-basic-recursive-caching-dns-server-and-configure-zones-for-domain.png?400|}} | ||
| + | |||
| + | Fiecare astfel de zonă conține câte o parte a arborelui, precum și numele serverelor care păstrează informația autorizată despre acea zonă. În mod normal, o zonă va avea un server de nume primar, care preia informația dintr-un fișier de pe discul propriu, și unul sau mai multe servere de nume secundare, care iau informația de la serverul primar. Pentru a îmbunătăți fiabilitatea, unele servere pentru o zonă pot fi plasate chiar în afara zonei. | ||
| + | |||
| + | Plasarea limitelor unei zone este la latitudinea administratorului ei. Această decizie este luată în mare parte pe baza numărului de servere de nume care se doresc a se folosi, și a locației acestora. Atunci când un resolver are o cerere referitoare la un nume de domeniu, el transferă cererea unuia din serverele locale de nume. Dacă domeniul este sub jurisdicția serverului de nume, el va întoarce înregistrări de resurse autorizate. O înregistrare autorizata (authoritative record) este cea care vine de la autoritatea care administrează înregistrarea, și astfel este întotdeauna corectă. Înregistrările autorizate se deosebesc de înregistrările din | ||
| + | memoria cache, care pot fi expirate. | ||
| + | |||
| + | Dacă totuși domeniul se află la distanță, iar local nu este disponibilă nici o informație despre el, atunci serverul de nume trimite un mesaj de cerere către serverul de nume de pe primul nivel al domeniului solicitat. De menționat că metoda de interogare este recursivă (recursive query), deoarece fiecare server care nu are informația cerută o caută în altă parte și raportează. | ||
| + | |||
| + | === API DNS === | ||
| + | |||
| + | == gethostbyname() și gethostbyaddr() == | ||
| + | |||
| + | Până de curând, pentru a afla un nume pe baza unei adrese IP și o adresă pe baza unui nume, se foloseau funcțiile [[https://linux.die.net/man/3/gethostbyname|gethostbyname()]] și [[https://linux.die.net/man/3/gethostbyaddr|gethostbyaddr()]], împreună cu structura //hostent//. Între timp, acest API pentru DNS a fost scos din uz. | ||
| + | |||
| + | == getaddrinfo() == | ||
| + | |||
| + | <code C> | ||
| + | #include <sys/types.h> | ||
| + | #include <sys/socket.h> | ||
| + | #include <netdb.h> | ||
| + | |||
| + | int getaddrinfo(const char *node, const char *service, | ||
| + | const struct addrinfo *hints, struct addrinfo **res); | ||
| + | </code> | ||
| + | |||
| + | Funcția [[https://linux.die.net/man/3/getaddrinfo|getaddrinfo()]] primește informații despre numele unei gazde și al unui serviciu Internet, și returnează adresa sau adresele corespunzătoare. Parametrul //node// reprezintă numele simbolic (sub forma unui șir de caractere) al mașinii căreia vrem sa-i aflăm adresa (de exemplu, node poate fi “www.google.com”). Mai poate de asemenea fi reprezentat ca un șir care conține o adresă IPv4 sau IPv6. | ||
| + | |||
| + | Parametrul //service// specifică portul returnat în output, și poate fi pus pe NULL (caz în care portul din output rămâne neinițializat) sau poate fi dat ca un nume de serviciu (de exemplu, “http”) sau ca o valoare numerică (“80”). | ||
| + | |||
| + | Parametrul //hints// reprezintă criterii pentru filtrarea adreselor întoarse de apelul funcției //getaddrinfo()//. Este de tipul //struct addrinfo//, definit mai jos: | ||
| + | |||
| + | <code C> | ||
| + | struct addrinfo { | ||
| + | int ai_flags; | ||
| + | int ai_family; | ||
| + | int ai_socktype; | ||
| + | int ai_protocol; | ||
| + | socklen_t ai_addrlen; | ||
| + | struct sockaddr *ai_addr; | ||
| + | char *ai_canonname; | ||
| + | struct addrinfo *ai_next; | ||
| + | }; | ||
| + | </code> | ||
| + | |||
| + | În cazul în care se dorește filtrarea, se pot completa unul sau mai multe din următoarele câmpuri (restul punându-se pe 0): | ||
| + | |||
| + | * //ai_family// - se specifică familia de adrese pentru valorile returnate, putând fi setată ca AF_INET (pentru IPv4), AF_INET6 (pentru IPv6) sau AF_UNSPEC (pentru ambele) | ||
| + | * //ai_socktype// - se filtrează după tipul de socket (SOCK_DGRAM sau SOCK_STREAM, de exemplu) | ||
| + | * //ai_protocol// - se specifică protocolul setat în adresele returnate de funcția //getaddrinfo()// | ||
| + | * //ai_flags// - se pot seta o serie de flag-uri. | ||
| + | |||
| + | În final, rezultatul este pus în parametrul //res//, fiind reprezentat ca o listă înlănțuită de structuri de tipul //addrinfo//, care se parcurge prin intermediul câmpului //ai_next//. Din câmpul //ai_addr// al rezultatului, se pot citi informațiile despre adresa și portul stației gazdă căutate (prin cast la //struct sockaddr_in//, de exemplu). | ||
| + | |||
| + | În caz de succes, funcția întoarce 0, iar în caz de eroare întoarce o valoare negativă, care poate fi interpretată prin intermediul funcției //gai_strerror()//: | ||
| + | |||
| + | <code C> | ||
| + | const char *gai_strerror(int errcode); | ||
| + | </code> | ||
| + | |||
| + | <note important> | ||
| + | Parametrul //res// este alocat de către funcția //getaddrinfo()//, însă el trebuie dezalocat explicit de către utilizator prin intermediul funcției //freeaddrinfo()//: | ||
| + | |||
| + | <code C> | ||
| + | void freeaddrinfo(struct addrinfo *res); | ||
| + | </code> | ||
| + | </note> | ||
| + | |||
| + | Pentru a afișa adresa IP (v4 sau v6) corespunzătoare numelui simbolic din parametrul //node//, se poate utiliza funcția //inet_ntop()//: | ||
| + | |||
| + | <code C> | ||
| + | #include <arpa/inet.h> | ||
| + | |||
| + | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); | ||
| + | </code> | ||
| + | |||
| + | Primul parametrul specifică familia de protocoale (AF_INET sau AF_INET6), al doilea parametru reprezintă structura de adresă (adică, de exemplu, câmpurile //sin_addr// sau //sin6_addr// din structurile //sockaddr_in// pentru IPv4 sau //sockaddr_in6// pentru IPv6), al treilea parametru reprezintă un șir de caractere unde va fi scrisă adresa sub formă de string, iar ultimul parametru reprezintă dimensiunea șirului de caractere în octeți. Valoarea de retur a funcției este un pointer la un șir de caractere identic cu cel din parametrul //dst//, sau NULL în caz de eroare. | ||
| + | |||
| + | == getnameinfo() == | ||
| + | |||
| + | |||
| + | <code C> | ||
| + | #include <sys/socket.h> | ||
| + | #include <netdb.h> | ||
| + | |||
| + | int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *host, | ||
| + | socklen_t hostlen, char *serv, socklen_t servlen, int flags); | ||
| + | </code> | ||
| + | |||
| + | Funcția [[https://linux.die.net/man/3/getnameinfo|getnameinfo()]] realizează operația inversă față de //getaddrinfo()//. Mai precis, primește o adresă și returnează numele simbolic și serviciul specifice adresei respective. Primii doi parametri reprezintă adresa IP (v4 sau v6) care este căutată. Se trimit structuri specifice protocolului dorit (//sockaddr_in// sau //sockaddr_in6//) și dimensiunea lor. Rezultatele apelului sunt puse în șirurile de caractere //host// și //serv//, care sunt alocate de către utilizator. Parametrii //hostlen// și //servlen// reprezintă dimensiunile celor două șiruri de caractere. | ||
| + | |||
| + | Funcția returnează 0 dacă s-a reușit cererea DNS, sau o valoare negativă interpretată cu //gai_strerror()// în caz contrar. | ||
| + | |||
| + | === Cereri DNS în Linux === | ||
| + | |||
| + | În Linux, pentru a obține adresele IP ale unei gazde, putem folosi unul din utilitarele //host// sau //nslookup//: | ||
| + | |||
| + | <code> | ||
| + | $ host google.com | ||
| + | google.com has address 172.217.20.14 | ||
| + | google.com has IPv6 address 2a00:1450:400d:804::200e | ||
| + | google.com mail is handled by 30 alt2.aspmx.l.google.com. | ||
| + | google.com mail is handled by 50 alt4.aspmx.l.google.com. | ||
| + | google.com mail is handled by 20 alt1.aspmx.l.google.com. | ||
| + | google.com mail is handled by 10 aspmx.l.google.com. | ||
| + | google.com mail is handled by 40 alt3.aspmx.l.google.com. | ||
| + | </code> | ||
| + | |||
| + | <code> | ||
| + | $ nslookup google.com | ||
| + | Server: 192.168.100.1 | ||
| + | Address: 192.168.100.1#53 | ||
| + | |||
| + | Non-authoritative answer: | ||
| + | Name: google.com | ||
| + | Address: 172.217.20.14 | ||
| + | </code> | ||
| + | |||
| + | Pentru aflarea unui nume pe baza unei adrese IP, se pot folosi tot //host// sau //nslookup//: | ||
| + | |||
| + | <code> | ||
| + | $ host 8.8.8.8 | ||
| + | 8.8.8.8.in-addr.arpa domain name pointer dns.google. | ||
| + | </code> | ||
| + | |||
| + | <code> | ||
| + | $ nslookup 8.8.8.8 | ||
| + | 8.8.8.8.in-addr.arpa name = dns.google. | ||
| + | |||
| + | Authoritative answers can be found from: | ||
| + | in-addr.arpa nameserver = a.in-addr-servers.arpa. | ||
| + | in-addr.arpa nameserver = b.in-addr-servers.arpa. | ||
| + | in-addr.arpa nameserver = c.in-addr-servers.arpa. | ||
| + | in-addr.arpa nameserver = e.in-addr-servers.arpa. | ||
| + | in-addr.arpa nameserver = d.in-addr-servers.arpa. | ||
| + | in-addr.arpa nameserver = f.in-addr-servers.arpa. | ||
| + | </code> | ||
| + | |||
| + | Un exemplu de output //tcpdump// pentru comanda //host// este mai jos (unde 53 este portul implicit pentru DNS): | ||
| + | |||
| + | <code> | ||
| + | $ sudo tcpdump port 53 | ||
| + | tcpdump: data link type PKTAP | ||
| + | tcpdump: verbose output suppressed, use -v or -vv for full protocol decode | ||
| + | listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes | ||
| + | |||
| + | 08:12:17.446368 IP 192.168.100.4.63991 > 192.168.100.1.domain: 31461+ A? google.com. (28) | ||
| + | 08:12:17.450412 IP 192.168.100.1.domain > 192.168.100.4.63991: 31461 1/0/0 A 172.217.16.110 (44) | ||
| + | 08:12:18.455598 IP 192.168.100.4.58146 > 192.168.100.1.domain: 4039+ AAAA? google.com. (28) | ||
| + | 08:12:18.463761 IP 192.168.100.1.domain > 192.168.100.4.58146: 4039 1/0/0 AAAA 2a00:1450:400d:803::200e (56) | ||
| + | 08:12:19.467330 IP 192.168.100.4.53016 > 192.168.100.1.domain: 58519+ MX? google.com. (28) | ||
| + | 08:12:19.514778 IP 192.168.100.1.domain > 192.168.100.4.53016: 58519 5/0/0 MX alt3.aspmx.l.google.com. 40, | ||
| + | MX alt4.aspmx.l.google.com. 50, MX aspmx.l.google.com. 10, MX alt1.aspmx.l.google.com. 20, | ||
| + | MX alt2.aspmx.l.google.com. 30 (136) | ||
| + | </code> | ||
| + | |||
| + | |||
| + | === Utilitarul dig === | ||
| + | |||
| + | [[https://linux.die.net/man/1/dig|dig]] (Domain Information Groper) este un utilitar Linux care interoghează servere de nume și afișează rezultatele într-o varietate de forme. | ||
| + | |||
| + | Înainte a vedea cum funcționează //dig//, este util să observăm formatul unui pachet DNS, prezentat mai jos (formatul fiecărei secțiuni se găsește detaliat în RFC [[https://www.ietf.org/rfc/rfc1035.txt|1035]]): | ||
| + | |||
| + | <code> | ||
| + | +---------------------+ | ||
| + | | Antet | | ||
| + | +---------------------+ | ||
| + | | Întrebare | întrebarea pentru serverul de nume | ||
| + | +---------------------+ | ||
| + | | Răspuns | RR-uri care răspund la întrebare | ||
| + | +---------------------+ | ||
| + | | Autoritate | RR-uri care indică o autoritate | ||
| + | +---------------------+ | ||
| + | | Adițional | RR-uri care conțin informație adițională | ||
| + | +---------------------+ | ||
| + | </code> | ||
| + | |||
| + | Pentru a interoga o singură gazdă, comanda de //dig// arată în felul următor: | ||
| + | |||
| + | <code> | ||
| + | $ dig google.com | ||
| + | </code> | ||
| + | |||
| + | Output-ul obținut se mapează pe structura unui răspuns standard DNS, cu mențiunea că unele din RR-uri (de exemplu, cele adiționale sau de autoritate) pot să lipsească. Prima parte a output-ului conține informații despre versiunea de //dig// folosită și opțiunile alese: | ||
| + | |||
| + | <code> | ||
| + | ; <<>> DiG 9.11.3-1ubuntu1.7-Ubuntu <<>> google.com | ||
| + | ;; global options: +cmd | ||
| + | </code> | ||
| + | |||
| + | Mai departe, urmează desfășurarea răspunsului primit de la server-ul DNS, începând cu antetul: | ||
| + | |||
| + | <code> | ||
| + | ;; Got answer: | ||
| + | ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35678 | ||
| + | ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 1 | ||
| + | </code> | ||
| + | |||
| + | În continuare, se afișează partea de întrebare (în exemplul nostru, pentru o adresă IPv4, adică A): | ||
| + | |||
| + | <code> | ||
| + | ;; QUESTION SECTION: | ||
| + | ;google.com. IN A | ||
| + | </code> | ||
| + | |||
| + | După întrebare, urmează RR-urile de răspuns (în cazul nostru, este unul singur, adică adresa IP a gazdei date): | ||
| + | |||
| + | <code> | ||
| + | ;; ANSWER SECTION: | ||
| + | google.com. 300 IN A 172.217.16.142 | ||
| + | </code> | ||
| + | |||
| + | Mai departe, secțiunea cu RR-uri de autoritate ne spune ce servere DNS pot să ne ofere răspunsuri autoritare la cererile noastre: | ||
| + | |||
| + | <code> | ||
| + | ;; AUTHORITY SECTION: | ||
| + | . 214056 IN NS c.root-servers.net. | ||
| + | . 214056 IN NS b.root-servers.net. | ||
| + | . 214056 IN NS a.root-servers.net. | ||
| + | . 214056 IN NS d.root-servers.net. | ||
| + | </code> | ||
| + | |||
| + | În continuare, ar putea urma secțiunea de RR-uri adiționale (care ar putea include, de exemplu, adresele serverelor de nume autoritare din secțiunea precedentă), iar la final ni se oferă statistici despre cerere: | ||
| + | |||
| + | <code> | ||
| + | ;; Query time: 37 msec | ||
| + | ;; SERVER: 172.16.10.254#53(172.16.10.254) | ||
| + | ;; WHEN: Thu Apr 09 07:32:54 EEST 2020 | ||
| + | ;; MSG SIZE rcvd: 266 | ||
| + | </code> | ||
| + | |||
| + | Așa cum se poate observa și mai sus, o cerere implicită de //dig// este realizată cu tipul A (adresă IPv4). Dacă se doresc altfel de cereri, acest lucru se poate specifica la rulare, imediat după numele gazdei. Pe lângă înregistrările propriu-zise, putem folosi și wildcard-ul ANY, care ne interoghează după toate tipurile de RR-uri: | ||
| + | |||
| + | <code> | ||
| + | $ dig ANY google.com | ||
| + | [...] | ||
| + | ;; ANSWER SECTION: | ||
| + | google.com. 283 IN AAAA 2a00:1450:400d:805::200e | ||
| + | google.com. 39 IN SOA ns1.google.com. dns-admin.google.com. 305440781 900 900 1800 60 | ||
| + | google.com. 25 IN A 172.217.20.14 | ||
| + | google.com. 26083 IN NS ns3.google.com. | ||
| + | [...] | ||
| + | </code> | ||
| + | |||
| + | Dacă nu ne interesează tot output-ul de mai sus și vrem să afișăm doar adresa IP (v4 sau v6), putem folosi opțiunea //+short//: | ||
| + | |||
| + | <code> | ||
| + | $ dig A google.com +short | ||
| + | 172.217.20.14 | ||
| + | |||
| + | $ dig AAAA google.com +short | ||
| + | 2a00:1450:400d:803::200e | ||
| + | </code> | ||
| + | |||
| + | Dacă dorim să nu afișăm vreuna din secțiunile de răspuns ale //dig//, putem alege din opțiunile de mai jos: | ||
| + | |||
| + | * //+nocomments// – nu se afișează liniile de comentarii | ||
| + | * //+noauthority// – nu se afișează secțiunea de RR-uri autoritare | ||
| + | * //+noadditional// – nu se afișează secțiunea de RR-uri adiționale | ||
| + | * //+nostats// – nu se afișează secțiunea de statistici | ||
| + | * //+noanswer// – nu se afișează secțiunea de răspuns. | ||
| + | |||
| + | Dacă dorim, putem dezactiva afișarea tuturor secțiunilor (cu opțiunea //+noall//) și apoi să alegem ce vrem să afișăm. Astfel, cele două comenzi de mai jos sunt echivalente, afișând doar secțiunea de răspuns: | ||
| + | |||
| + | <code> | ||
| + | $ dig google.com +nocomments +noquestion +noauthority +noadditional +nostats | ||
| + | |||
| + | ; <<>> DiG 9.10.6 <<>> google.com +nocomments +noquestion +noauthority +noadditional +nostats | ||
| + | ;; global options: +cmd | ||
| + | google.com. 56 IN A 216.58.214.238 | ||
| + | |||
| + | $ dig google.com +noall +answer | ||
| + | |||
| + | ; <<>> DiG 9.10.6 <<>> google.com +noall +answer | ||
| + | ;; global options: +cmd | ||
| + | google.com. 43 IN A 216.58.214.23 | ||
| + | </code> | ||
| + | |||
| + | În mod implicit, //dig// folosește serverele de nume din fișierul ///etc/resolv.conf//. Totuși, dacă dorim, putem specifica serverul de nume pe care îl interogăm în felul următor: | ||
| + | |||
| + | <code> | ||
| + | $ dig @8.8.8.8 google.com | ||
| + | [...] | ||
| + | |||
| + | $ dig @ns1.google.com google.com | ||
| + | [...] | ||
| + | </code> | ||
| + | |||
| + | Dacă se dorește interogarea unui server DNS pentru un număr mai mare de gazde (o interogare de tip //bulk//), acest lucru se poate face prin adăugarea lor într-un fișier și folosirea opțiunii //-f//: | ||
| + | |||
| + | <code> | ||
| + | $ cat queries.txt | ||
| + | google.com | ||
| + | facebook.com | ||
| + | twitter.com | ||
| + | |||
| + | $ dig -f queries.txt +noall +answer | ||
| + | google.com. 106 IN A 172.217.19.110 | ||
| + | facebook.com. 43 IN A 185.60.218.35 | ||
| + | twitter.com. 1052 IN A 104.244.42.193 | ||
| + | twitter.com. 1052 IN A 104.244.42.1 | ||
| + | </code> | ||
| + | |||
| + | Așa cum s-a menționat și mai sus, sistemul DNS este organizat ierarhic, deci o cerere //dig// parcurge mai multe servere DNS. Acest lucru se poate observa prin intermediul parametrului //+trace//: | ||
| + | |||
| + | <code> | ||
| + | $ dig google.com +noall +answer +trace | ||
| + | </code> | ||
| + | |||
| + | Pentru a realiza o căutare inversă (reverse lookup), se folosește opțiunea //-x// pentru a obține domeniul și numele asociate cu un IP: | ||
| + | |||
| + | <code> | ||
| + | $ dig -x 8.8.8.8 +noall +answer | ||
| + | |||
| + | ; <<>> DiG 9.10.6 <<>> -x 8.8.8.8 +noall +answer | ||
| + | ;; global options: +cmd | ||
| + | 8.8.8.8.in-addr.arpa. 17648 IN PTR dns.google. | ||
| + | </code> | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== E-mail ==== | ||
| Un mesaj e-mail a fost întotdeauna transmis în format plain-text (text clar). Chiar si prin adăugarea atașamentelor, mesajele de e-mail sunt trimise tot ca mesaje plain-text, prin folosirea unor mecanisme de codificare (//uuencode/uudecode//, //MIME/BASE64//). | Un mesaj e-mail a fost întotdeauna transmis în format plain-text (text clar). Chiar si prin adăugarea atașamentelor, mesajele de e-mail sunt trimise tot ca mesaje plain-text, prin folosirea unor mecanisme de codificare (//uuencode/uudecode//, //MIME/BASE64//). | ||
| Line 109: | Line 522: | ||
| Se observă faptul că părțile care compun mesajul sunt separate între ele printr-un șir de caractere separator (boundary string), specificat ca un parametru pentru antetul //Content-Type//. Fiecare parte poate avea la rândul ei propriile antete, care conțin în general tipul și numele fișierului din secțiunea respectivă. În cazul în care se trimit atașamente binare, acestea sunt codificate folosind schema numită Base64, descrisă în [[https://tools.ietf.org/html/rfc1521|RFC 1521]]. | Se observă faptul că părțile care compun mesajul sunt separate între ele printr-un șir de caractere separator (boundary string), specificat ca un parametru pentru antetul //Content-Type//. Fiecare parte poate avea la rândul ei propriile antete, care conțin în general tipul și numele fișierului din secțiunea respectivă. În cazul în care se trimit atașamente binare, acestea sunt codificate folosind schema numită Base64, descrisă în [[https://tools.ietf.org/html/rfc1521|RFC 1521]]. | ||
| + | |||
| ==== Protocoalele SMTP, POP3 și IMAP ==== | ==== Protocoalele SMTP, POP3 și IMAP ==== | ||
| Line 206: | Line 620: | ||
| ==== Suportul de laborator ==== | ==== Suportul de laborator ==== | ||
| - | ===I. Email=== | + | |
| - | Va oferim [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/bogdan_costel.mocanu-master-patch-08393/Email|aici]] un cod sursă schelet pentru realizarea unui client de email SMTP scris in C. Veți folosi un server SMTP acre rulează local. Acesta poate fi creat folosind un utilitar existent în Python, numit //smtpd//. Rularea acestui utiliar pe portul 25 se face astfel: | + | ===I. DNS=== |
| + | Va oferim [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/master/lab11|aici]] un cod sursă schelet pentru realizarea unei aplicații in C care utilizează API-ul DNS. | ||
| + | |||
| + | ===II. Email=== | ||
| + | Va oferim [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/master/lab11|aici]] un cod sursă schelet pentru realizarea unui client de email SMTP scris in C. Veți folosi un server SMTP acre rulează local. Acesta poate fi creat folosind un utilitar existent în Python, numit //smtpd//. Rularea acestui utiliar pe portul 25 se face astfel: | ||
| <code> | <code> | ||
| Line 217: | Line 635: | ||
| </note> | </note> | ||
| - | ===II. DNS=== | ||
| - | Va oferim [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/bogdan_costel.mocanu-master-patch-08393/dns|aici]] un cod sursă schelet pentru realizarea unei aplicații in C care utilizează API-ul DNS. | ||
| ==== Exerciții ==== | ==== Exerciții ==== | ||
| - | ===I. E-mail=== | + | ===I. DNS=== |
| - | Pornind de la codul disponibil [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/bogdan_costel.mocanu-master-patch-08393/Email|aici]], implementați următoatrea cerință: | + | |
| - | 1. Implementați un client SMTP peste TCP prin care să trimiteți către serverul //smtpd// un e-mail care conține niște text și un fișier dat ca parametru sub forma unui atașament de tip //text/plain// (API-ul necesar pentru conexiunea TCP cu server-ul este detaliat în [[https://ocw.cs.pub.ro/courses/pc/laboratoare/07|laboratorul 7]]). | + | Pornind de la codul disponibil [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/master/lab11|aici]], implementați următoatrea cerință: |
| - | + | ||
| - | == Bonus == | + | |
| - | + | ||
| - | - Folosind instrucțiunile de [[https://www.dropbox.com/s/d382g7f705uo6bq/SMTP_Google.pdf?dl=0|aici]], trimiteți un e-mail către asistent prin intermediul serverului SMTP de la Google. | + | |
| - | + | ||
| - | ===II. DNS=== | + | |
| - | + | ||
| - | Pornind de la codul disponibil [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/bogdan_costel.mocanu-master-patch-08393/dns|aici]], implementați următoatrea cerință: | + | |
| 1. Scrieți un program care să afișeze numele și adresele IP pentru un host. Programul poate primi ca parametru fie numele (caz în care se va afișa adresa), fie adresa IP (caz în care se va afișa numele). Testați-va programul folosind informațiile din tabelul de mai jos. Exemplu de apel: <code> | 1. Scrieți un program care să afișeze numele și adresele IP pentru un host. Programul poate primi ca parametru fie numele (caz în care se va afișa adresa), fie adresa IP (caz în care se va afișa numele). Testați-va programul folosind informațiile din tabelul de mai jos. Exemplu de apel: <code> | ||
| Line 247: | Line 654: | ||
| ^ Tip ^ Gazdă ^ Răspuns ^ TTL ^ Prioritate ^ | ^ Tip ^ Gazdă ^ Răspuns ^ TTL ^ Prioritate ^ | ||
| | **Pentru single-v4 există o singură adresă IPv4** ||||| | | **Pentru single-v4 există o singură adresă IPv4** ||||| | ||
| - | | A | single-v4.protocoale.xyz | 127.0.0.1 | 300 | | + | | A | single-v4.protocoale.life | 127.0.0.1 | 300 | |
| | **Pentru single-v4 există o singură adresă IPv6** ||||| | | **Pentru single-v4 există o singură adresă IPv6** ||||| | ||
| - | | AAAA | single-v6.protocoale.xyz | ::1 | 300 | | + | | AAAA | single-v6.protocoale.life | ::1 | 300 | |
| | ** Pentru single se definesc 2 adrese (una IPv4 si una IPv6)** ||||| | | ** Pentru single se definesc 2 adrese (una IPv4 si una IPv6)** ||||| | ||
| - | | A | single.protocoale.xyz | 127.0.0.1 | 300 | | + | | A | single.protocoale.life | 127.0.0.1 | 300 | |
| - | | AAAA | single.protocoale.xyz | ::1 | 300 | | + | | AAAA | single.protocoale.life | ::1 | 300 | |
| - | | **Spațiul dorinel.protocoale.xyz este delegat către un alt server de nume ce rulează la adresa potato.dfilip.xyz** ||||| | + | | **Spațiul dorinel.protocoale.life este delegat către un alt server de nume ce rulează la adresa potato.dfilip.xyz** ||||| |
| - | | NS | dorinel.protocoale.xyz | potato.dfilip.xyz | 300 | | + | | NS | dorinel.protocoale.life | potato.dfilip.xyz | 300 | |
| | **Pentru multi-v4 există 4 adrese IPv4** ||||| | | **Pentru multi-v4 există 4 adrese IPv4** ||||| | ||
| - | | A | multi-v4.protocoale.xyz | 127.1.1.1 | 300 | | + | | A | multi-v4.protocoale.life | 127.1.1.1 | 300 | |
| - | | A | multi-v4.protocoale.xyz | 127.2.2.2 | 300 | | + | | A | multi-v4.protocoale.life | 127.2.2.2 | 300 | |
| - | | A | multi-v4.protocoale.xyz | 127.3.3.3 | 300 | | + | | A | multi-v4.protocoale.life | 127.3.3.3 | 300 | |
| - | | A | multi-v4.protocoale.xyz | 127.4.4.4 | 300 | | + | | A | multi-v4.protocoale.life | 127.4.4.4 | 300 | |
| | **Pentru multi-v6 există 4 adrese IPv6** ||||| | | **Pentru multi-v6 există 4 adrese IPv6** ||||| | ||
| - | | AAAA | multi-v6.protocoale.xyz | ::1 | 300 | | + | | AAAA | multi-v6.protocoale.life | ::1 | 300 | |
| - | | AAAA | multi-v6.protocoale.xyz | ::2 | 300 | | + | | AAAA | multi-v6.protocoale.life | ::2 | 300 | |
| - | | AAAA | multi-v6.protocoale.xyz | ::3 | 300 | | + | | AAAA | multi-v6.protocoale.life | ::3 | 300 | |
| - | | AAAA | multi-v6.protocoale.xyz | ::4 | 300 | | + | | AAAA | multi-v6.protocoale.life | ::4 | 300 | |
| | **Pentru multi se definesc 8 adrese (4 de IPv4 și 4 de IPv6)** ||||| | | **Pentru multi se definesc 8 adrese (4 de IPv4 și 4 de IPv6)** ||||| | ||
| - | | A | multi.protocoale.xyz | 127.1.1.1 | 300 | | + | | A | multi.protocoale.life | 127.1.1.1 | 300 | |
| - | | A | multi.protocoale.xyz | 127.2.2.2 | 300 | | + | | A | multi.protocoale.life | 127.2.2.2 | 300 | |
| - | | A | multi.protocoale.xyz | 127.3.3.3 | 300 | | + | | A | multi.protocoale.life | 127.3.3.3 | 300 | |
| - | | A | multi.protocoale.xyz | 127.4.4.4 | 300 | | + | | A | multi.protocoale.life | 127.4.4.4 | 300 | |
| - | | AAAA | multi.protocoale.xyz | ::1 | 300 | | + | | AAAA | multi.protocoale.life | ::1 | 300 | |
| - | | AAAA | multi.protocoale.xyz | ::2 | 300 | | + | | AAAA | multi.protocoale.life | ::2 | 300 | |
| - | | AAAA | multi.protocoale.xyz | ::3 | 300 | | + | | AAAA | multi.protocoale.life | ::3 | 300 | |
| - | | AAAA | multi.protocoale.xyz | ::4 | 300 | | + | | AAAA | multi.protocoale.life | ::4 | 300 | |
| | **Adresele pc->pcom->protocoale definesc un șir de nume canonice care are la capăt o adresă IPv4** ||||| | | **Adresele pc->pcom->protocoale definesc un șir de nume canonice care are la capăt o adresă IPv4** ||||| | ||
| - | | CNAME | pc.protocoale.xyz | pcom.protocoale.xyz | 300 | | + | | CNAME | pc.protocoale.life | pcom.protocoale.life | 300 | |
| - | | CNAME | pcom.protocoale.xyz | protocoale.protocoale.xyz | 300 | | + | | CNAME | pcom.protocoale.life | protocoale.protocoale.life | 300 | |
| - | | A | protocoale.protocoale.xyz | 127.42.42.42 | 300 | | + | | A | protocoale.protocoale.life | 127.42.42.42 | 300 | |
| | **Emailul este deservit de 3 servere SMTP cu priorități diferite** ||||| | | **Emailul este deservit de 3 servere SMTP cu priorități diferite** ||||| | ||
| - | | MX | protocoale.xyz | alt1.gmail-smtp-in.l.google.com | 300 | 10 | | + | | MX | protocoale.life | alt1.gmail-smtp-in.l.google.com | 300 | 10 | |
| - | | MX | protocoale.xyz | alt2.gmail-smtp-in.l.google.com | 300 | 20 | | + | | MX | protocoale.life | alt2.gmail-smtp-in.l.google.com | 300 | 20 | |
| - | | MX | protocoale.xyz | alt3.gmail-smtp-in.l.google.com | 300 | 30 | | + | | MX | protocoale.life | alt3.gmail-smtp-in.l.google.com | 300 | 30 | |
| ^ Tip ^ Gazdă ^ Răspuns ^ TTL ^ Prioritate ^ | ^ Tip ^ Gazdă ^ Răspuns ^ TTL ^ Prioritate ^ | ||
| </spoiler> | </spoiler> | ||
| + | ===II. E-mail=== | ||
| + | Pornind de la codul disponibil [[https://gitlab.cs.pub.ro/protocoale-de-comunicatie/pcom-laboratoare-public/-/tree/master/lab11|aici]], implementați următoatrea cerință: | ||
| + | |||
| + | 1. Implementați un client SMTP peste TCP prin care să trimiteți către serverul //smtpd// un e-mail care conține niște text și un fișier dat ca parametru sub forma unui atașament de tip //text/plain// (API-ul necesar pentru conexiunea TCP cu server-ul este detaliat în [[https://ocw.cs.pub.ro/courses/pc/laboratoare/07|laboratorul 7]]). | ||
| + | |||
| + | == Bonus == | ||
| + | |||
| + | - Folosind instrucțiunile de [[https://www.dropbox.com/s/d382g7f705uo6bq/SMTP_Google.pdf?dl=0|aici]], trimiteți un e-mail către asistent prin intermediul serverului SMTP de la Google. | ||