Protocolul SOCKS. Server proxy universal

Când lucrați cu proxy, este foarte important să alegeți tipul potrivit de proxy pentru sarcinile dvs., pentru a le evita posibile problemeși atinge-ți obiectivele. Cele mai utilizate sunt proxy-urile HTTP și proxy-urile Socks5. Diferențele dintre ele constă în gradul de anonimat, protocolul utilizat, metoda de transmitere a datelor folosită atunci când lucrați ca proxy, precum și în unele funcții suplimentare. Să ne uităm la fiecare tip de proxy separat.

Caracteristicile proxy HTTP

Să începem cu proxy-ul HTTP. În timpul lucrului lor, folosesc protocolul HTTP, care este destinat pentru vizitarea site-urilor, descărcarea și transferul de fișiere și atunci când lucrează cu unele programe care folosesc acest protocol pentru a se conecta printr-un proxy. Solicitările făcute atunci când se lucrează cu servere proxy HTTP nu sunt trimise direct, ci folosesc serverul proxy ca intermediar, trimițând cereri în numele acestuia.

De asemenea, în protocolul HTTP proxy este disponibilă caching-ul, care accelerează încărcarea paginii prin utilizarea fișierelor salvate, precum și monitorizarea și filtrarea traficului din rețea, stabilirea limitelor de viteză, blocarea resurselor nedorite, colectarea de statistici prin salvarea jurnalelor etc.

Proxy-urile acestui protocol diferă în ceea ce privește gradul de anonimat. Iasă în evidență următoarele tipuri Proxy HTTP pentru anonimat:

Proxy-uri transparente care nu maschează adresa IP reală și, de asemenea, nu ascund faptul că un server proxy este utilizat pentru a accesa resursa. Astfel de proxy-uri sunt rareori utilizate, în principal pentru a redirecționa utilizatorul către un alt server proxy,

Proxy anonim. Ei transmit informații despre utilizarea proxy-urilor, cu toate acestea, adresa dvs. IP este mascată și înlocuită cu o altă adresă IP, oferind un nivel de securitate sigur.

Proxy de elită. Ele ascund utilizarea proxy-urilor și, de asemenea, maschează în mod fiabil adresa IP, ceea ce le face cele mai sigure dintre proxy-urile HTTP. Serverul pe care încercați să îl accesați va presupune că conexiunea dvs. este directă, fără a utiliza un server proxy.

De asemenea, ar trebui să evidențiem proxy-urile HTTPS care utilizează protocolul SSL. Sunt un subtip al protocolului HTTP care utilizează o conexiune securizată. Traficul de rețea transmis de acești proxy este criptat în siguranță, ceea ce garantează cel mai înalt nivel de anonimat. De regulă, astfel de proxy sunt utilizați pentru a asigura securitatea rețelelor bancare, în organizațiile comerciale pentru a crea securitate rețele corporativeși în alte conexiuni care necesită securitate. Alte caracteristici sunt aceleași cu cele ale protocolului HTTP.

Caracteristicile proxy Socks5

Un alt protocol care este popular printre utilizatori este Socks5. Serverele proxy care lucrează cu acest protocol sunt inițial anonime, deoarece transmit traficul de rețea formă pură fără a expune antetele HTTP. Prin urmare, serverul pe care încercați să îl accesați nu va ști că utilizați un server proxy și nu va primi adresa dumneavoastră IP.

Socks5 proxy, acceptă următoarele protocoale de rețea: HTTP, HTTPS, FTP și caracteristicile acestora: cache, Conexiune SSL,autentificare. În plus, proxy-urile de protocol Socks5 folosesc conexiuni UDP și TPC, ceea ce le extinde domeniul de aplicare și le face cele mai funcționale dintre serverele proxy moderne. Inițial, protocolul Socks5 trebuia să funcționeze software. Din acest motiv, majoritatea programelor acceptă acest protocol pentru conectarea printr-un proxy. Serverele proxy Socks5 au și o caracteristică drăguță care vă permite să construiți lanțuri de servere proxy, ceea ce este util pentru rezolvarea unor probleme atunci când lucrați pe Internet.

Dacă comparați proxy-urile HTTP și Socks5, este de preferat să folosiți pe acestea din urmă. Din moment ce sunt mai anonimi, susțin mai multe caracteristiciși, de asemenea, lucrează cu orice site-uri și programe care acceptă conectarea printr-un proxy. Puteți vizita site-ul nostru prin plasarea unei comenzi în contul dvs. personal.

Articolul este dedicat protocolului SOCKS5 - structura sa internă, aplicația practică, precum și serverele și clienții SOCKS disponibili pentru platforma Unix

[Valentin Sinitsyn (val AT linuxcenter DOT ru)]

„Îmi pare rău, Pooh”, a spus SAVA. - Tigger a mestecat toate firele de pe serverul de mail, iar corespondența nu a mai ajuns de mult...
„Fire”, gândi Pooh supărat. - Tricotează șosete din aceste fire.

Andrey Shcherbakov „9600 baud și atât, asta este, asta este...”

În acest articol vom vorbi despre protocolul SOCKS[ notă de subsol: „socks” - engleză. „șosete”, „ciorapi”]. Cu ajutorul lui poți rezolva cel mai mult sarcini diferite: organizați accesul securizat la serviciile situate în spatele unui firewall, ascundeți adresa IP adevărată atunci când lucrați cu resurse de rețea neprietenoase sau implementați un server proxy universal care acceptă orice protocoale la nivel de aplicație (HTTP, FTP, POP3/SMTP, ICQ etc.). Din păcate, în ciuda simplității și bogăției SOCKS, mulți administratori de sistem nu sunt foarte familiarizați cu acesta și nu au idee cum poate fi util. Aș dori să sper că, după citirea acestui material, protocolul nemeritat uitat își va lua locul cuvenit în arsenalul lor. Să facem o rezervare imediat: toate prezentările ulterioare se vor referi la a cincea versiune de SOCKS, SOCKS5. Versiunea anterioară, a patra (SOCKS4) este încă în circulație pe Internet, cu toate acestea, capabilitățile sale sunt mai limitate.

Apropo, numele protocolului nu are nimic de-a face cu articolele de ciorapi menționate în epigraf și este o simplă abreviere pentru „SOCK-et-S” - „sockets” sau, într-o traducere mai familiară a unui specialist în computer. ureche, „prize”. Termenul a fost propus de creatori ca opțiune de lucru și s-a blocat. După cum știți, socket-urile sunt baza oricărui API care se implementează networking- Unix, Winsock etc. Pentru a trimite date prin rețea, o aplicație trebuie pur și simplu să le scrie într-un socket, similar cu ceea ce se face atunci când stochează informații într-un fișier local. În ambele cazuri, programul nu trebuie să-și facă griji cu privire la ceea ce se întâmplă „în spatele scenei” - adăugarea datelor utilizatorului cu informații despre serviciu, împărțirea lor în segmente cu încapsularea lor ulterioară în datagrame și trimiterea fizică este efectuată de alte părți ale sistemul de operare - stiva TCP / IP și driverele de dispozitiv despre care aplicația nu știe nimic. Această „diviziune a muncii” vă permite să modificați procedura de livrare a mesajelor după cum doriți, cu condiția ca interfața de programare a aplicației să rămână constantă. Această caracteristică este cea care stă la baza ideologiei SOCKS. Sarcina principală a acestui protocol este de a introduce în procesul „normal” de schimb de date un anumit intermediar numit server SOCKS sau proxy SOCKS. Când un client (o aplicație care acceptă SOCKS: browser web Mozilla, client ICQ Miranda IM etc., vezi mai jos) dorește să trimită orice informație prin rețea, stabilește o conexiune nu cu destinatarul real, ci cu serverul SOCKS, care, la rândul său, înaintează datele către destinație, dar în nume propriu. Din punctul de vedere al serverului „real” (de exemplu, site-ul web pe care utilizatorul dorește să îl vadă Mozilla Firefox) Proxy SOCKS este cel mai comun client. Astfel, identitatea (adresa IP) a clientului adevărat este ascunsă de serverul care îl servește. Această circumstanță foarte convenabilă este plină de pericol potențial (vă puteți ascunde Tu, dar pot de la tine), prin urmare, serverele SOCKS din viața reală au dezvoltat scheme de control al accesului (interzicând conexiunile de intrare și de ieșire la o anumită listă de adrese) și acceptă autorizarea utilizatorului folosind o parolă (vezi mai jos).

Rețineți că, deoarece SOCKS funcționează la un nivel mai scăzut decât nivelul aplicației (și anume, transport) al modelului OSI, suportul acestuia nu va necesita nicio modificare a logicii clientului, cu atât mai puțin a serverului. Într-adevăr, tot ceea ce este necesar este modificarea implementării funcțiilor responsabile cu crearea conexiune la rețeași trimiterea datelor: connect(), bind(), send(), etc. În practică, acest lucru se realizează de obicei prin interceptarea apelurilor de sistem și apoi înlocuirea lor cu omologii definiți de utilizator activați de SOCKS. Nicio modificare a codului sursă aplicații client, cu atât mai puțin accesul la textele sursă, de regulă, nu este necesar. Această procedură puternică este cunoscută sub numele de „soxificare” și va fi discutată în detaliu mai jos.

Acum că avem o înțelegere generală a SOCKS, putem trece la o privire mai detaliată. a acestui protocol.

Specificația SOCKS5

Protocolul SOCKS5 este descris în detaliu în RFC1928. Spre deosebire de standardele monstruoase precum HTTP 1.1, specificația SOCKS se încadrează în 9 pagini și poate fi analizată cu ușurință de oricine. Informațiile oferite aici sunt un scurt rezumat al acestora și au scopul de a vă ajuta în această problemă simplă.

După cum sa menționat mai devreme, SOCKS5 este un protocol de nivel de transport. „Vecinii” săi - TCP și UDP sunt utilizați direct pentru a transmite date care provin din stratul de aplicație (de la aplicații personalizate), ceea ce înseamnă că proxy-ul SOCKS trebuie să poată funcționa corect cu fiecare dintre ele. De asemenea, rețineți că protocolul ICMP folosit de utilitatile ping și traceroute este situat sub stratul de transport și, prin urmare, din păcate, nu poate fi cosificat.[ Notă de subsol: există extensii non-standard la protocolul SOCKS care vă permit să lucrați cu ICMP, cu toate acestea, acestea nu vor fi discutate în acest articol].

Înainte de a trimite orice date, clientul trebuie să treacă printr-o procedură de autorizare pe serverul SOCKS. Pentru a face acest lucru, deschide o conexiune TCP la portul 1080 (valoarea implicită) al serverului SOCKS și trimite peste acesta un mesaj care conține numerele de cod ale metodelor de autentificare pe care le acceptă. Serverul SOCKS selectează una dintre metode la discreția sa și raportează numărul acesteia clientului. O listă a unora dintre valorile posibile este dată în Tabelul 1. După cum puteți vedea cu ușurință, autentificarea poate fi absentă (în practică, aceasta înseamnă cel mai probabil că serverul SOCKS distinge clienții după adresele lor IP) sau pe baza unui nume de utilizator si parola. În acest din urmă caz ​​este posibil număr mare diverse opțiuni, de la banala „Autentificare nume de utilizator/parolă” (RFC 1929) care prevede transmiterea unei parole către formă deschisă la mult mai sigur CHAP (parolă criptată, date clare) și GSSAPI (RFC 1961), care pot fi folosite pentru a proteja complet criptografic traficul. După autorizarea cu succes, clientul este capabil să trimită cereri (comenzi), să stabilească conexiuni de ieșire și chiar să le primească pe cele primite.

Stabilirea unei conexiuni TCP de ieșire

Pentru a stabili o conexiune TCP de ieșire, clientul trimite o solicitare „CONNECT” către serverul SOCKS, care specifică adresa și portul de livrare. Pentru a identifica nodul destinatar, atât adresele IP (sunt acceptate IPv4/IPv6) cât și cu drepturi depline nume de domenii. În acest din urmă caz, serverul SOCKS se ocupă de rezolvarea acestora, astfel că rețeaua în care activează clientul se poate, în principiu, să se facă fără un server DNS. În mesajul de răspuns, serverul SOCKS raportează un cod de eroare (ca de obicei, 0 indică faptul că operația a avut succes), precum și adresa IP (BND.ADDR) și portul TCP (BND.PORT) care vor fi folosite efectiv pentru comunica cu nodul solicitat. Deoarece serverele SOCKS au de obicei mai multe interfata de retea, adresa IP dată poate diferi de cel cu care a fost stabilită legătura de control. Clientul deschide apoi o nouă sesiune TCP cu BND.ADDR:BND.PORT și trimite date. Conexiunea TCP de ieșire este încheiată când sesiunea de control este închisă. Rețineți că o solicitare CONNECT poate fi respinsă de un proxy SOCKS dacă adresele sursă (client) sau destinație (server) sunt interzise [ Notă de subsol: sau nu este permis în mod explicit, în funcție de implementarea specifică și politica aleasă] la service administrator de sistem.

Stabilirea unei conexiuni UDP de ieșire

Spre deosebire de protocolul de streaming TCP, care implică stabilirea unei sesiuni, protocolul UDP este bazat pe datagrame și, prin urmare, este ceva mai complex de utilizat. Suportul său a apărut doar în SOCKS5.

Înainte de a trimite datagrame UDP, clientul solicită serverul SOCKS Asociația UDP folosind comanda „UDP ASSOCIATE”. O asociere UDP este un fel de sesiune virtuală între un client și un server SOCKS. În cererea de ieșire, clientul specifică pretinsadresa și portul care vor acționa ca sursă a viitoarelor datagrame UDP. Dacă această informație nu este încă cunoscută când asocierea UDP este stabilită, clientul ar trebui să folosească combinația 0.0.0.0:0 (sau, de exemplu, x.x.x.x:0 dacă doar numărul portului este necunoscut). În mesajul de răspuns, serverul SOCKS specifică adresa IP (BND.ADDR) și portul UDP (BND.PORT) către care ar trebui trimise datagramele de ieșire. În acest caz, adresa și portul destinatarului lor real sunt indicate direct în corp (putem spune că are loc încapsularea UDP). E tu parametrii, împreună cu adresa și portul expeditorului, sunt utilizați pentru a decide dacă o datagramă poate fi trimisă. După cum puteți vedea cu ușurință, acest lucru creează o încărcare suplimentară pe serverul SOCKS: regulile de filtrare trebuie aplicate fiecărei datagrame UDP, în timp ce în cazul unei conexiuni TCP, legitimitatea acesteia este evaluată o dată, în momentul în care serverul SOCKS execută „ comanda CONECTARE”. Conform standardului, serverul SOCKS trebuie să se asigure că adresa IP a expeditorului de datagramă se potrivește cu adresa gazdei care a creat asocierea UDP. Asocierea UDP este distrusă concomitent cu închiderea sesiunii de control TCP în care a fost trimisă comanda UDP ASSOCIATE.

Multe dintre serverele SOCKS existente întâmpină probleme serioase dacă un firewall NAT (Network Address Translation) este plasat între ele și clientul care solicită asocierea UDP. Motivul pentru aceasta constă în modificarea adresei sursă și a portului care are loc în momentul în care datagrama UDP traversează firewall-ul. Ca urmare, serverul și aplicația client nebănuitoare încep să vorbească limbi diferite: adresa sursă și portul dorit specificate în comanda „UDP ASSOCIATE” nu mai corespund parametrilor reali ai datagramelor primite de serverul SOCKS. Ca urmare, acestea sunt aruncate ca neaparținând asociației UDP. Problema ar putea fi rezolvată prin specificarea 0.0.0.0:0 ca sursă intenționată (vezi mai sus), care ar trebui interpretată de serverul SOCKS ca „orice datagramă UDP care provine de la aceeași adresă ca și comanda de creare a asocierii”. Din păcate, majoritatea serverelor SOCKS interpretează standardul mai restrâns și nu vă permit să setați simultan atât adresa dorită, cât și portul expeditorului la zero. Dintre implementările testate de autor, „trucul cu redirecționarea UDP prin NAT” descris aici permite să se facă doar una - Dante.

Primirea conexiunilor de intrare

Această caracteristică destul de originală poate fi utilă în cazurile în care clientul și serverul „real” din schema descrisă mai sus sunt schimbate, ceea ce se poate întâmpla, de exemplu, în protocoale precum FTP. În scopul unei discuții ulterioare, vom presupune că între „client” (partea care intenționează să accepte conexiune de intrare) iar „serverul” (partea care inițiază conexiunea de intrare) a stabilit deja un canal de comunicare „direct” folosind comanda „CONNECT”. Pentru a deschide un canal „reverse”, „clientul” trebuie să trimită comanda „BIND” către serverul SOCKS, specificând în parametrii acestuia adresa IP și portul pe care îl va folosi pentru a primi conexiunea de intrare. Ca răspuns, serverul SOCKS raportează adresa IP și portul alocat acestuia pentru a menține canalul „invers”. Se așteaptă ca „clientul” să transmită acești parametri „server” folosind facilitățile oferite de protocoalele de nivel de aplicație (de exemplu, comanda FTP „PORT”). După ce serverul SOCKS acceptă (sau respinge) conexiunea de intrare, re-notifică „clientul”, spunându-i adresa IP și portul folosit de „server”. Rețineți că conexiunile de intrare pot fi acceptate doar de o aplicație ai cărei dezvoltatori s-au ocupat de suportul SOCKS în etapa de proiectare. În caz contrar (dacă aplicația funcționează cu serverul SOCKS printr-un program sockets), nu va putea furniza informații corecte despre adresa socket-ului care așteaptă „feedback” (adică va genera comanda incorectă „PORT” în exemplul FTP discutat mai sus).

ȘOSETE „Lanțuri”.

Haide, treci la treabă. Șase routere închiriate „la un moment dat” prin care circulă semnalul. Și toate sunt destul de rezistente la hacking.

Serghei Lukyanenko „Labirintul reflecțiilor”

Arhitectura protocolului SOCKS5 facilitează combinarea serverelor SOCKS în cascade, sau așa cum sunt numite și „lanțuri”. Este de remarcat faptul că toate acțiunile necesare pentru aceasta pot fi efectuate pe partea clientului. Singura cerință pentru „legăturile” lanțului este că acestea trebuie „încredere” unul în celălalt (adică, să permită stabilirea conexiunilor de intrare și de ieșire). Dacă serverele SOCKS care formează cascada nu sunt anonime (adică folosesc Username/Parolă, CHAP sau scheme de autentificare similare), este de asemenea necesar ca utilizatorul să poată finaliza cu succes procedura de autorizare pe fiecare dintre ele.

Să presupunem că avem un set de N servere SOCKS numite socks1, socks2, ..., socksN, care satisfac toate cerințele de mai sus. Apoi, pentru a crea o cascadă, clientul poate face următoarele:

    În cazul în care conexiune TCP de ieșire: clientul se conectează la socks1, parcurge procedura de autorizare (dacă este necesar) și trimite comanda „CONNECT”, specificând socks2 ca adresă de livrare. Prin executarea acestei solicitări, socks1 va crea o nouă conexiune cu socks2 și va transfera în mod regulat toate informațiile care trec prin ea către client, în timp ce socks2 nici măcar nu va ghici cu cine comunică de fapt. Procedura se repetă apoi până când se stabilește o legătură între șosete (N-1) și șoseteN. Ultimul server din cascadă se conectează direct la nodul care interesează clientul. Transferul de date are loc ca de obicei: clientul trimite un pachet către serverul socks1, care, la rândul său, îl transmite către socks2, ... și așa mai departe până când se ajunge la nodul final.

    În cazul în care conexiune UDP de ieșire: clientul se conectează la socks1, trece prin procedura de autorizare și trimite secvenţial două comenzi: „CONNECT” (adresă de livrare - socks2) și „UDP ASSOCIATE”. Astfel, sunt create două conexiuni noi: un canal UDP virtual între client și socks1 și o sesiune TCP între socks1 și socks2.

Folosind această sesiune TCP, clientul (în numele socks1) trimite comanda „UDP ASSOCIATE” la serverul socks2 (deschide un canal UDP între socks1 și socks2) și „CONNECT” la serverul socks3.Procedura continuă până când sunt stabilite canale UDP virtuale între toate serverele SOCKS din cascadă. Pentru a trimite orice date, clientul efectuează mai întâi încapsularea în N-fold a datagramei UDP, specificând secvenţial socks1, socks2, socks3, socksN şi adresa destinatarului real ca adresă de livrare, apoi o trimite către serverul socks1. Rețineți că, în practică, această opțiune în cascadă este extrem de rară. Acest lucru se datorează faptului că serverele SOCKS, cum ar fi firewall-urile NAT, pot schimba portul sursă al datagramei, ceea ce va duce la probleme descrise în detaliu în secțiunea „Stabilirea unei conexiuni UDP de ieșire”. Folosind lanțuri de servere SOCKS care nu necesită autentificare, clientul poate crește semnificativ anonimatul lucrului pe Internet (vezi epigraf). Puteți găsi multe programe pe Internet care implementează schemele descrise aici. Acestea, de exemplu, sunt SocksChain ( http://www.ufasoft.com/socks/) pentru Windows sau ProxyChains ( ).

) pentru Unix. Serverele SOCKS în cascadă este, de asemenea, o parte integrantă a unor soxifier, în special FreeCap (

Acum că principiile de funcționare ale unui server SOCKS ne sunt bine cunoscute, este timpul să trecem de la teorie la practică. Există un număr mare de programe în lume care implementează protocolul SOCKS5. Acestea acoperă toate sistemele de operare populare (Unix, Windows, ...) și metodele de distribuție (freeware, shareware, open-source etc.). Aici vom lua în considerare pe scurt cele mai faimoase (sau interesante din punctul de vedere al autorului) implementări.

Să începem cu SOCKS5 Reference Implementation (http://www.socks.permeo.com/), realizată de NEC și deținută de momentul prezent Compania Permeo. Versiunea actuală este numerotată 1.0r11 și este datată august 2000. După cum puteți ghici cu ușurință din nume, acest server este o implementare de referință a protocolului și, în general, nu este destinat utilizării industriale. Totuși, din motive care nu îmi sunt foarte clare, a fost inclus în porturile FreeBSD și, prin urmare, este un standard de facto pe această platformă. Produsul are suport GSSAPI și este distribuit în cod sursă, dar sub o licență proprietară. Utilizarea comercială a acestui server este interzisă.

Dante, dezvoltat de compania norvegiană Inferno Nettverk, este deosebit de popular printre suporterii Linux. Produsul se dezvoltă, deși nu foarte rapid (cea mai recentă versiune, 1.1.15, este datată 31 ianuarie 2005) și este destul de potrivit pentru utilizare practică. După cum am menționat mai devreme, Dante permite asocierilor UDP să funcționeze corect chiar dacă trec printr-un firewall NAT. Programul este distribuit în cod sursă sub licența BSD. Dante include o bibliotecă pentru coxificarea transparentă a aplicațiilor Unix (vezi mai jos)

Valentin Sinitsyn (val AT linuxcenter DOT ru) - Server proxy universal

Cu ceva timp în urmă am vrut să încerc să implementez un server proxy pentru nevoile mele și unul care ar putea fi folosit în viitor și, de asemenea, ca dimensiunea lui să fie minimă. Opțiunea naturală pentru mine a fost implementarea folosind assembler. Programul s-a dovedit a fi mic, convenabil, iar pe viitor l-am folosit foarte des. Dar acum, după ani de zile, aș vrea să arăt cea mai simplă implementare un singur protocol, SOCKS4. Acest protocol a fost creat astfel încât clienții aflați în rețeaua locală din spatele firewall-ului să poată accesa rețeaua externă. În același timp, în acest caz, este posibil să controlați cererile clienților :) Primul lucru pe care trebuie să-l faceți atunci când implementați este să citiți documentația care descrie acest protocol, deoarece dorim ca protocolul nostru să fie înțeles de programele standard, fără „subminare cu un fișier.” Deci, documentația:

Acum, înarmați cu o descriere, să începem. Sarcina unui server proxy este de a accepta o solicitare de la un client într-un anumit format, de a genera un socket și de a-l conecta la adresa solicitată de client, iar apoi de a asigura schimbul de date între două socket-uri până când acestea sunt închise de către server. sau client. Să începem implementarea.

Macro-uri și structuri de date utilizate în program

Să creăm un fișier include, includes.inc. În acest fișier vom plasa macrocomenzi + structuri standard pentru lucrul cu SOCKS4 atunci când scriem programe Windows. Aici nu voi da toate macrocomenzile, voi da doar descrierea și funcționalitatea necesară pentru a rezolva problema principală, tot ce veți găsi în fișierul atașat cu codurile sursă.
; SOCKS4 – Structura utilizată de client la solicitarea unei conexiuni; la serverul specificat(DSTIP)/port(DSTPORT) CONNECT_SOCK4 Struc VN Db ?

CD Db? DSTPORT Dw? DSTIP Dd?
NULL Db? CONNECT_SOCK4 Se termină ; SOCKS4 - răspunsul serverului proxy despre conexiune. RESPONSE_SOCK4 Struc VN Db ?
CD Db?
DSTPORT Dw?
* Iar cea de-a treia etapă finală este trimiterea de date între priza client și priza creată și conectată de noi la adresa solicitată.

Implementarea primei etape, inițializarea programului:

; Procedura principală este procedura de pornire pentru programul WinMain Proc LOCAL ThreadId, hServSock:DWORD LOCAL nume gazdă :BYTE LOCAL _wsa:WSADATA LOCAL _our:sockaddr_in ; Lansând biblioteca pentru lucrul cu socket-uri, folosim funcționalitatea versiunii 1.1, ; să-l cerem ca minim invoke WSAStartup, 0101h, ADDR _wsa .if eax == 0 ; Luăm adresa noastră, pregătim o structură pentru a inițializa socket-ul serverului invoke gethostname, ADDR hostname, 256 invoke gethostbyname, ADDR hostname .if eax == 0 invoke inet_addr, ADDR hostname .else mov eax, mov eax, mov eax, .endif mov _our.sin_addr, eax invoke inet_ntoa, eax mov _our.sin_family, AF_INET mov _our.sin_addr.S_un.S_addr, INADDR_ANY xor eax, eax ; Introduceți portul pe care vrem să ascultăm mesajele primite mov ax, SOCKS_PORT invoke htons, eax mov _our.sin_port, ax invoke socket, AF_INET, SOCK_STREAM, 0 .if eax != INVALID_SOCKET ; Salvați socket-ul serverului creat mov hServSock, eax ; Legăm socket-ul serverului la adresa noastră și la portul necesar invoke bind, hServSock, ADDR _our, SIZEOF sockaddr_in .if eax != SOCKET_ERROR @@: ; Inițiază socket-ul pentru a aștepta invoke listen, hServSock, SOMAXCONN .repeat ; Un client a sosit, primim un socket cu clientul primit invoke accept, hServSock, NULL, NULL .until eax != INVALID_SOCKET ; Creați un fir în care clientul curent va fi procesat xchg eax, ebx invoke CreateThread, NULL, NULL, ADDR socketThread, ebx, NULL, ADDR ThreadId ; Lăsăm să așteptăm clienții jmp @B .endif .endif invoke closesocket, hServSock .endif invoke ExitProcess, 0 WinMain Endp
Aceasta este prima noastră procedură, am încercat să comentez codul cât mai mult posibil, astfel încât să vă puteți da seama, dar dacă ceva încă nu este clar, vă rugăm să mă contactați fie pe mine, fie pe MSDN. Practic, tot codul este scris folosind sintaxa MASM și WinAPI. Rezultatul funcției de mai sus ar trebui să fie o priză funcțională pe unul dintre adrese de rețea mașina dvs. (adresă locală sau adresă externă dacă aveți o IP reală) + pe baza conexiunii la client, funcția creează un fir separat folosit pentru a lucra cu clientul de intrare. Acum hai sa mergem mai departe...

Etapa a doua, analiza cererii clientului

În al doilea pas, tot ce trebuie făcut este să acceptați o structură CONNECT_SOCK4, să creați un socket, să încercați să îl conectați și să trimiteți un răspuns clientului. Implementare:

SocketThread Proc sock:DWORD LOCAL lpMem, _csock, ThreadId, dAmount:DWORD LOCAL Remote:sockaddr_in LOCAL wrFds, rdFds:fd_set LOCAL hResp:RESPONSE_SOCK4 ; Pregătirea pentru a citi datele din socket invocă FdZero, ADDR rdFds invocă FdSet, sock, ADDR rdFds invocă selectează, NULL, ADDR rdFds, NULL, NULL, NULL ; Obținem dimensiunea datelor care așteaptă să fie citite invoke ioctlsocket, sock, FIONREAD, ADDR dAmount ; Rezervăm memorie pentru date mov lpMem, @Result(LocalAlloc, LMEM_FIXED sau LMEM_ZEROINIT, dAmount) ; Citiți datele cererii de la socket invoke recv, sock, lpMem, dAmount, 0; Solicitarea a venit lea edi, hResp mov esi, lpMem ; ESI conține o cerere de utilizator. Ne ocupăm (aici) doar de versiunea SOCKS4, ; SOCKS5 poate fi, în principiu, procesat aici, dar asta va veni mai târziu... Presupunem Esi: Ptr CONNECT_SOCK4 Presupunem Edi: Ptr RESPONSE_SOCK4 .if .VN == 4 ; Implementarea protocolului SOX 4 .if .CD == 1 invoke socket, AF_INET, SOCK_STREAM, 0 .if eax != INVALID_SOCKET mov _csock, eax ; Luăm datele gazdei la distanță cu care clientul dorește să se conecteze mov Remote.sin_family, AF_INET mov ax, .DSTPORT mov Remote.sin_port, ax mov eax, .DSTIP mov Remote.sin_addr, eax mov cx, .DSTPORT mov edx , .DSTIP ; Edi conține răspunsul utilizatorului mov .VN, 0 mov .DSTPORT, cx mov .DSTIP, edx ; Încercăm să ne conectăm cu server la distanță invoke connect, _csock, ADDR Remote, SIZEOF Remote .if !eax ; Pregătim un răspuns că am conectat mov .CD, 90 ; Trimitem clientului un răspuns care conține rezultatul încercării de conectare invoke send, sock, ADDR hResp, SIZEOF RESPONSE_SOCK4, 0 ; Formăm o structură cu informații despre server și; prize client conectate; - prin server aici ma refer la priza conectata la client; cine a trimis cererea; - prin client ma refer la o priza conectata la server; ale căror date au fost solicitate de clientul mov ebx, @Result(LocalAlloc, LMEM_FIXED sau LMEM_ZEROINIT, SIZEOF THREAD_DATA) Presupuneți Ebx: Ptr THREAD_DATA mov eax, _csock mov .Server, eax mov eax, eax mov eax: ; Începem firul de procesare a socketului (citirea de la client și transmiterea către socket-ul serverului) invoke CreateThread, NULL, NULL, ADDR ClientSock, ebx, NULL, ADDR ThreadId .else ; Dacă conexiunea eșuează, închideți socket-ul client invoke closesocket, _csock ; Spunem că a existat o eroare de conectare mov , 91 ; Trimitem clientului un răspuns care conține rezultatul încercării de conectare invoke send, sock, ADDR hResp, SIZEOF RESPONSE_SOCK4, 0 .endif .endif .endif .endif Assume Edi: Nothing Assume Esi: Nothing ; Eliberarea memoriei alocate pentru cerere invoke LocalFree, lpMem ret socketThread Endp
Rezultatul acestei proceduri este un socket conectat, precum și un fir creat care implementează schimbul de date între două prize. Este simplu. Trebuie doar să clarificăm că mai multe puncte de adresare sunt folosite aici în cadrul structurilor care au fost introduse în MASM pentru a ușura viața programatorului. Primul punct, macro-ul „Asumați”.
Linia Presupune Esi: Ptr CONNECT_SOCK4 spune compilatorului că acest registru (Esi) conține adresa structurii CONNECT_SOCK4, ceea ce simplifică și mai mult accesarea variabilelor din această structură. Să presupunem că Esi: Nimic nu anulează legarea. Pentru a înțelege mai bine, ar putea fi mai ușor dacă aș enumera câteva opțiuni de adresare:
Presupunem Esi:Ptr CONNECT_SOCK4 mov al, .VN ; Plasam in AL valoarea octet din variabila VN structura mov al, .CD ; Plasați axul variabil CD mov în AL. .DSTPORT ; Plasați variabila DSTPORT în AX Assume Esi:Nothing
sau
mov al, ; Plasați valoarea octetului din variabila VN în AL mov al, ; Plasați axul variabil CD mov, ; Plasați variabila DSTPORT în AX
sau
mov al, byte ptr; Plasați variabila VN în AL mov al, byte ptr ; Plasați variabila CD în AL mov ax, word ptr ; Plasați variabila DSTPORT în AX

Cred că este evident pentru tine, așa cum este și pentru mine, că este mai rapid, mai convenabil și mai clar să folosești prima opțiune. Deși, dacă este necesar să ne referim la o variabilă a structurii, a doua opțiune are dreptul de a exista. Cred că este mai bine să folosiți a treia opțiune în cazurile în care datele de la adresă nu sunt structurate. Dar, după cum știți, fiecare lup Tambov are gustul și culoarea lui. Utilizați metoda care vă este cea mai convenabilă.
Încă un punct care merită clarificat. Macro-rezultat. Această macrocomandă a fost scrisă astfel încât să puteți apela o funcție WinAPI într-o singură linie și să scrieți rezultatul execuției într-un registru sau memorie. Deci linia:
mov lpMem, @Result(LocalAlloc, LMEM_FIXED sau LMEM_ZEROINIT, dAmount)
Mai întâi faceți un apel ca acesta:
invocați LocalAlloc, LMEM_FIXED sau LMEM_ZEROINIT, dAmount
iar după executarea acestui apel, rezultatul execuției (Eax) este stocat în variabila lpMem. În acest caz particular, memoria va fi alocată, iar adresa la care se află zona alocată pentru noi va fi scrisă în variabilă.

Etapa a treia, transferul de date

Deci, cele mai dificile două etape au fost finalizate. Clientul a sosit, l-am conectat la serverul de la distanță și a venit timpul pentru cea mai simplă muncă „maimuță”. Transferați date între două prize. Să o facem rapid și ușor:
; Un flux care citește din socket-ul clientului și îl trimite la socket-ul serverului... ClientSock Proc Param:DWORD LOCAL server, sclient:DWORD LOCAL rdFds:fd_set LOCAL dAmount, lpBuf: DWORD ; În Param avem informații despre server și socket-uri client; transfer la variabilele locale mov ebx, Param Assume Ebx: Ptr THREAD_DATA mov eax, .Server mov server, eax mov eax, .Client mov sclient, eax Presupun Ebx: Nimic ; Nu uitați să eliberați memoria invocă LocalFree, Param @@: invocă FdZero, ADDR rdFds invocă FdSet, server, ADDR rdFds invocă FdSet, sclient, ADDR rdFds invocă selectează, NULL, ADDR rdFds, NULL, NULL; Verificați dacă există date de citit.if eax == SOCKET_ERROR || eax == 0 ; Fără date - exit jmp @F .endif ; Există date de la server care trebuie transmise clientului? invocă FdIsSet, server, ADDR rdFds .if eax ; Obținem dimensiunea datelor care așteaptă să fie citite invoke ioctlsocket, server, FIONREAD, ADDR dAmount ; Rezervați memorie pentru date mov lpBuf, @Result(LocalAlloc, LMEM_FIXED sau LMEM_ZEROINIT, dAmount) invoke recv, server, lpBuf, dAmount, 0 .if eax == SOCKET_ERROR || eax == 0 jmp @F .endif invoke send, sclient, lpBuf, eax, 0 invoke LocalFree, lpBuf .endif ; Există date de la client de trimis la socket-ul serverului? invocă FdIsSet, sclient, ADDR rdFds .if eax ; Obținem dimensiunea datelor care așteaptă să fie citite invoke ioctlsocket, sclient, FIONREAD, ADDR dAmount ; Rezervă memorie pentru date mov lpBuf, @Result(LocalAlloc, LMEM_FIXED sau LMEM_ZEROINIT, dAmount) invoke recv, sclient, lpBuf, dAmount, 0 .if eax == SOCKET_ERROR || eax == 0 jmp @F .endif invocă trimitere, server, lpBuf, eax, 0 invocă LocalFree, lpBuf .endif ; Să mergem la
ciclu nou
jmp @B @@: ; Închideți socket-urile invoke closesocket, server invoke closesocket, sclient ; Ieșiți din firul de invocare ExitThread, 0 ClientSock Endp Inițial, această procedură inițializează variabilele interne din structura transmisă în flux pentru a le face mai ușor de utilizat. Apoi, în buclă, se face o verificare pentru a vedea dacă sunt date de citit din socketuri, apoi în două bucăți de cod (de fapt copy-paste, aici nu m-am deranjat să scot funcția și să o optimizez pentru că e mai clar ) citește de la o priză și trimite-l la al doilea.– FireFox. În setările de conectare indicăm că trebuie să folosim un server proxy SOCKS4. Indicăm adresa acestuia și portul pe care se află. După aceea, salvăm setările și ne bucurăm de internet, trecut prin proxy-ul nostru, cu o dimensiune de 3,5 kbytes))) Da, voi clarifica. Pentru compilare este necesar să aveți pachetul instalat

Un astfel de server proxy controlează drepturile clientului de a accesa resurse externe și transmite cererea către server. SOCKS poate fi folosit și în sens invers, permițând clienților externi să se conecteze la servere în spatele unui firewall.

Spre deosebire de serverele proxy HTTP, SOCKS transmite toate datele de la client fără a adăuga nimic de la sine, adică din punctul de vedere al serverului final, proxy-ul SOCKS este un client obișnuit. SOCKS este mai universal - nu depinde de protocoale specifice stratului de aplicație (nivelul 7 al modelului OSI) și se bazează pe standardul TCP/IP - protocolul layer 4. Dar proxy-ul HTTP memorează în cache datele și poate filtra mai atent conținutul datelor transmise.

Acest protocol a fost dezvoltat de David Koblas, administrator de sistem pentru MIPS Computer Systems. După ce MIPS a devenit parte a Silicon Graphics (SGI) în acel an, Koblas a susținut o discuție despre SOCKS la Simpozionul de securitate Usenix, iar SOCKS a devenit disponibil public. Protocolul a fost extins la versiunea 4 de Ying-Da Lee de la NEC Systems Laboratory.

Protocol SOCKS 4

SOCKS 4 este proiectat să funcționeze printr-un firewall fără autentificare pentru aplicațiile client-server care rulează pe TCP, cum ar fi TELNET, FTP și protocoale de comunicare populare, cum ar fi HTTP, WAIS și GOPHER. În esență, un server SOCKS poate fi gândit ca un firewall care acceptă protocolul SOCKS.

O solicitare tipică SOCKS 4 arată astfel (fiecare câmp este de un octet):

Solicitarea clientului către SOCKS Server:

  • câmpul 1: numărul versiunii SOCKS, 1 octet (ar trebui să fie 0x04 pentru această versiune)
  • câmpul 2: cod de comandă, 1 octet:
    • 0x02 = Alocarea portului TCP/IP (legare)
  • câmpul 3: numărul portului, 2 octeți
  • câmpul 4: adresa IP, 4 octeți
  • câmpul 5: ID utilizator, șir de lungime variabilă, terminat cu un octet nul (0x00). Câmpul are scopul de a identifica utilizatorul (vezi Ident)

Răspunsul serverului la clientul SOCKS:

  • câmpul 1: octet nul
  • câmpul 2: cod de răspuns, 1 octet:
    • 0x5a = cererea acordată
    • 0x5b = cerere respinsă sau invalidă
    • 0x5c = Solicitarea a eșuat deoarece identd nu rulează (sau nu este accesibil de pe server)
    • 0x5d = Solicitarea a eșuat deoarece ID-ul clientului nu a putut valida ID-ul utilizatorului din cerere
  • câmpul 3: 2 octeți arbitrari, ar trebui ignorați
  • câmpul 4: 4 octeți arbitrari, ar trebui ignorați

Protocol SOCKS 5

SOCKS 5 extinde modelul SOCKS 4 prin adăugarea de suport UDP, oferind scheme universale autentificare puternică și extinde metodele de adresare prin adăugarea de suport pentru nume de domenii și adrese IPv6. Instalare inițială Conexiunea constă acum din următoarele:

  • Clientul se conectează și trimite o salutare care include o listă de metode de autentificare acceptate
  • Serverul alege una dintre ele (sau trimite un răspuns de eșec la cerere dacă niciuna dintre metodele propuse nu este acceptabilă)
  • În funcție de metoda aleasă, un număr de mesaje pot trece între client și server
  • Clientul trimite o cerere de conectare, similară cu SOCKS 4
  • Serverul răspunde, similar cu SOCKS 4

Metodele de autentificare sunt numerotate după cum urmează:

  • 0x00 - nu este necesară autentificarea
  • 0x01 - GSSAPI
  • 0x02 - nume de utilizator/parolă
  • 0x03-0x7F - rezervat de IANA
  • 0x80-0xFE - rezervat metodelor de utilizare privată

Salutare inițială din partea clientului:

  • câmpul 2: numărul de metode de autentificare acceptate, 1 octet
  • câmpul 3: numere de metodă de autentificare, lungime variabilă, 1 octet pentru fiecare metodă acceptată

Serverul raportează alegerea sa:

  • câmpul 1: versiunea SOCKS, 1 octet (0x05 pentru această versiune)
  • câmpul 2: metoda de autentificare selectată, 1 octet sau 0xFF dacă nu a fost propusă nicio metodă acceptabilă

Identificarea ulterioară depinde de metoda aleasă.

Solicitarea clientului:

  • câmpul 1: numărul versiunii SOCKS (ar trebui să fie 0x05 pentru această versiune)
  • câmpul 2: cod de comandă, 1 octet:
    • 0x01 = configurarea conexiunii TCP/IP
    • 0x02 = Alocarea portului TCP/IP (legare)
    • 0x03 = Asociere porturi UDP
  • câmpul 3: octet rezervat, trebuie să fie 0x00
  • câmpul 4: tipul adresei, 1 octet:
    • 0x01 = adresa IPv4
    • 0x03 = nume de domeniu
    • 0x04 = adresa IPv6
  • câmpul 5: atribuirea adresei
    • 4 octeți pentru adresa IPv4
    • 16 octeți pentru adresa IPv6
  • câmpul 6: numărul portului, 2 octeți

Răspunsul serverului:

  • câmpul 1: numărul versiunii SOCKS, 1 octet (0x05 pentru această versiune)
  • câmpul 2: cod de răspuns, 1 octet:
    • 0x00 = cererea acordată
    • 0x01 = Eroare de server SOCKS
    • 0x02 = conexiunea este interzisă de setul de reguli
    • 0x03 = rețea indisponibilă
    • 0x04 = gazda inaccesibilă
    • 0x05 = conexiune refuzată
    • 0x06 = TTL a expirat
    • 0x07 = Comanda nu este acceptată / eroare de protocol
    • 0x08 = tipul de adresă nu este acceptat
  • câmpul 3: octet rezervat, trebuie să fie 0x00
  • câmpul 4: tipul de adresă ulterior, 1 octet:
    • 0x01 = adresa IPv4
    • 0x03 = nume de domeniu
    • 0x04 = adresa IPv6
  • câmpul 5: atribuirea adresei
    • 4 octeți pentru adresa IPv4
    • primul octet este lungimea numelui, urmat de numele de domeniu fără un nul final
    • 16 octeți pentru adresa IPv6
  • câmpul 6: numărul portului, 2 octeți

Implementări

  • Sun Java System Web Proxy Server - server proxy de stocare în cache pentru Solaris, Linux, Windows. Suportă HTTPS, filtre I/O NSAPI, reconfigurare dinamică și proxy invers.
  • DeleGate este un gateway multifuncțional la nivel de aplicație și un server proxy care rulează pe diverse platforme. Pe lângă SOCKS, acceptă și HTTP(S), FTP, NNTP, SMTP, POP, IMAP, LDAP, Telnet, DNS și alte protocoale.
  • 3proxy - server proxy ușor cu suport SOCKS-proxy
  • WinGate este un server proxy multi-protocol cu ​​suport SOCKS pentru Windows.
  • OpenSSH vă permite să creați dinamic tuneluri definite printr-un subset al protocolului SOCKS.

Vezi de asemenea

  • Tor este o rețea anonimă de rutare a ceapă cu o interfață SOCKS.

Legături

  • RFC 1928 - Protocolul SOCKS versiunea 5
  • RFC 1928 (rusă) - Protocol SOCKS 5
  • RFC 1929 - Autentificare nume de utilizator/parolă pentru SOCKS V5
  • RFC 1961 (engleză) - Metodă de autentificare GSS-API pentru SOCKS versiunea 5
  • SOCKS: Un protocol pentru proxy TCP peste firewall - protocol SOCKS 4

Fundația Wikimedia.

2010.

    Vezi ce este „SOCKS” în alte dicționare:ȘOSETE

    Vezi ce este „SOCKS” în alte dicționare:- este un protocol de Internet care permite aplicațiilor client server să utilizeze în mod transparent serviciile unui firewall de rețea. SOCKS este o abreviere pentru SOCKetS [ ]… … Wikipedia

    - Căutați navigarea, căutarea SOCKS este un protocol de Internet care permite aplicațiilor. Clientul server folosește într-un mod transparent serviciile unui firewall de red. SOCKS este o abreviare a SOCKETS. Los clientes que hay detrás… … Wikipedia Español Protocol de rețea care permite clientului aplicații server

    utilizați în mod transparent serviciile din spatele firewall-urilor. SOCKS este prescurtare de la SOCKetS (prize). Clienții din spatele unui firewall care au nevoie de acces la... ... WikipediaȘosete

    utilizați în mod transparent serviciile din spatele firewall-urilor. SOCKS este prescurtare de la SOCKetS (prize). Clienții din spatele unui firewall care au nevoie de acces la... ... Wikipedia- Im Briefing Room des Weißen Hauses Betty Currie und Socks … Deutsch Wikipedia