Relay-ul VPN nu mai acceptă SSH: limite ale descriptorilor de fișier
Traficul tunelului continuă să curgă în timp ce relay-ul socat din spate refuză sesiuni noi. Urmați calea, apoi citiți limita moștenită pe PID-ul viu.
Un handshake WireGuard încă se finalizează, peer-ul încă arată un endpoint recent, și totuși o sesiune SSH nouă prin relay-ul din spate rămâne blocată fără banner. Combinația aceea indică departe de tunel și către procesul care acceptă socket-ul. Un relay ca socat stă în calea aplicației cu propriul buget de descriptori, propriii copii și propriile limite moștenite. Parcursul de mai jos începe la client și se oprește la prima componentă care nu mai poate deschide un socket.
Urmați calea înainte de a schimba un număr
Urmați o singură cerere eșuată în loc să raționați despre tunel ca întreg. Clientul scrie în tunel, daemonul VPN decriptează și rutează, iar relay-ul acceptă pe cealaltă parte. Fiecare pas consumă descriptori, iar cel care de obicei se epuizează este ultimul.
Începeți cu o cerere pe care o puteți reproduce și măsurați-i timpul. Dacă handshake-ul TCP se finalizează, dar nu sosește niciun banner al aplicației, relay-ul a luat socket-ul și apoi s-a blocat într-un copil sau pe piciorul său upstream. Dacă handshake-ul în sine nu se finalizează niciodată, cauza este rutarea, firewall-ul sau starea ascultătorului, nu un plafon de descriptori. Notați care dintre cele două forme ați observat-o, pentru că indică procese diferite.
Numărați și salturile care dublează munca. Un ascultător care se ramifică predă fiecare socket acceptat unui copil care păstrează propria copie, așa că totalul real este o proprietate a întregului arbore, nu doar a părintelui.
Citiți limita pe care relay-ul a moștenit-o
Singura limită care contează aparține procesului aflat în execuție și a fost stabilită de ceea ce a lansat acel proces. Tastarea ulimit -n într-un shell descrie shell-ul. Întrebați managerul de servicii ce a aplicat, apoi confirmați pe PID.
systemctl show -p MainPID -p LimitNOFILE vpn-relay.service
cat /proc/$(systemctl show -p MainPID --value vpn-relay.service)/limits
Fișierul limits tipărește plafoanele soft și hard așa cum le vede procesul. O valoare soft mică sub o valoare hard generoasă înseamnă că daemonul are voie să își ridice propriul plafon, iar unele o fac la pornire; valori soft egale și mici înseamnă că fișierul unit este sursa.
Fișierele drop-in se încarcă în ordine lexicografică și fișierele ulterioare câștigă, deci systemctl cat vpn-relay.service este vizualizarea autoritativă a ceea ce se aplică. Editarea unui fișier pe care managerul nu îl citește niciodată este cel mai frecvent motiv pentru care un număr ridicat nu are efect.
Separați concurența stabilă de starea reținută
Două procese pot atinge același plafon din motive nelegate, iar remediile diferă. Cererea care urmărește sesiuni concurente utile este o chestiune de capacitate. Creșterea care continuă după terminarea lucrului este o scurgere sau un set de sesiuni pe care nimeni nu le-a închis.
Măsurați în repaus, la vârful normal și din nou câteva minute după ce sarcina se oprește. Numărarea intrărilor deschise cu ls /proc/PID/fd | wc -l față de limita soft vă spune diferența, iar un număr cu unu sau doi sub plafon este o oprire dură, nu o cale lentă.
Când numărul refuză să scadă, priviți stările socket-urilor, nu totalurile. Descriptorii care stau în CLOSE_WAIT înseamnă că peer-ul a închis, iar partea dumneavoastră nu a făcut-o niciodată, ceea ce este un defect al ciclului de viață al aplicației pe care o limită mai mare doar îl amână. Limitați și modelul copiilor: un relay care se ramifică fără plafon la copiii concurenți epuizează descriptorii, sloturile de proces și memoria împreună.
Verificați noua valoare pe procesul viu
După ce editați unit-ul, reîncărcați managerul și reporniți serviciul, deoarece o reîncărcare singură nu înlocuiește niciodată limitele pe care un proces aflat în execuție le-a moștenit deja. Verificați pe procesul care servește efectiv trafic.
systemctl daemon-reload
systemctl restart vpn-relay.service
awk '/Max open files/ {print}' /proc/$(systemctl show -p MainPID --value vpn-relay.service)/limits
ss -tnp state established '( sport = :2222 )' | wc -l
Linia awk returnează noua pereche; dacă încă o arată pe cea veche, drop-in-ul pe care l-ați editat nu este cel încărcat. Numărul de ss este verificarea sarcinii, așa că deschideți numărul de sesiuni pe care îl așteptați și urmăriți-l cum crește. Un număr care continuă să crească după ce acele sesiuni se închid înseamnă că limita nu a fost niciodată toată problema.
O precizare însoțește orice creștere mare. Aplicațiile care interoghează cu select() nu pot supraveghea descriptori peste FD_SETSIZE, care este 1024 în build-urile tipice, așa că un plafon ridicat dincolo de asta poate produce eșecuri care par nelegate. Referința de execuție systemd poartă același avertisment pentru serviciile pe care le pornește.
Țineți repornirea departe de disponibilitatea tunelului
Repornirea relay-ului îi elimină sesiunile active, iar acesta este un eveniment separat de căderea VPN-ului. Ordonați schimbarea astfel încât tunelul să rămână sus în timp ce relay-ul se rotește, și avertizați pe oricine a cărui sesiune lungă îl traversează.
Revenirea este fișierul unit anterior plus încă o repornire, iar acel fișier rămâne la locul lui până când noua valoare supraviețuiește o zi de lucru. Apoi închideți bucla cu cererea care a eșuat inițial: o sesiune SSH nouă prin relay, un transfer suficient de lung ca să conteze și un număr de descriptori care revine la nivelul său de repaus.