1 poin oleh GN⁺ 2025-01-06 | 1 komentar | Bagikan ke WhatsApp
  • NAT Traversal adalah teknologi dasar yang membuat perangkat di balik NAT dan firewall dapat bertukar paket UDP secara langsung, sehingga Tailscale bisa menghubungkan tunnel WireGuard tanpa hub pusat
  • Prasyarat utamanya adalah protokolnya berbasis UDP, dan paket untuk penelusuran NAT serta paket komunikasi sebenarnya harus bisa dikirim dan diterima lewat soket jaringan yang sama
  • Firewall stateful hanya mengizinkan respons yang cocok dengan paket UDP yang lebih dulu keluar, jadi jika para peer mengetahui ip:port satu sama lain dan mengirim paket hampir bersamaan, mereka dapat membuka state firewall
  • Karena NAT mengubah IP dan port sumber, diperlukan teknik pelengkap seperti STUN, pemetaan port, penanganan NAT64, penelusuran port berbasis paradoks ulang tahun, dan relay
  • ICE menguji kandidat jalur yang memungkinkan secara bersamaan lalu memilih jalur terbaik, sementara Tailscale terhubung lebih dulu lewat relay DERP dan kemudian beralih secara transparan jika menemukan jalur langsung yang lebih baik

Syarat dasar NAT Traversal

  • Tujuannya adalah membuat aliran paket UDP dua arah di antara dua perangkat, lalu menjalankan protokol seperti WireGuard, QUIC, dan WebRTC di atasnya
  • Jika ingin mengimplementasikannya langsung, ada dua syarat penting
    • Protokolnya harus berbasis UDP
      • Ini juga bisa dilakukan dengan TCP, tetapi kompleksitasnya lebih tinggi, dan tergantung cara implementasinya bisa memerlukan modifikasi kernel
      • Jika membutuhkan koneksi berorientasi stream, Anda bisa mempertimbangkan QUIC yang berjalan di atas UDP
    • Program harus mengendalikan langsung soket jaringan yang mengirim dan menerima paket
      • NAT Traversal perlu mengirim paket tambahan di luar protokol utama, sehingga sulit jika hanya ditambahkan begitu saja ke library jaringan yang sudah ada
      • Struktur di mana logika NAT Traversal dan protokol utama berbagi soket yang sama dan berjalan paralel sangat berguna
  • Jika akses soket langsung sulit, Anda bisa menaruh proxy lokal
    • Protokol aslinya berkomunikasi dengan proxy
    • Proxy menangani NAT Traversal dan relay paket ke peer

Menembus firewall stateful

  • Firewall stateful mengingat paket yang pernah dilihat sebelumnya untuk menentukan apakah paket baru boleh lewat
    • Contohnya seperti Windows Defender firewall, Ubuntu ufw, BSD pf, pf di macOS, dan AWS Security Groups
    • Konfigurasi yang umum adalah mengizinkan semua koneksi outbound dan memblokir semua koneksi inbound
  • Pada UDP, aturannya sederhana
    • Jika firewall melihat paket UDP keluar dari 2.2.2.2:1234 ke 5.5.5.5:5678, maka firewall akan mengizinkan paket masuk sebaliknya dari 5.5.5.5:5678 ke 2.2.2.2:1234
    • Beberapa firewall yang lebih longgar bisa mengizinkan trafik masuk dari mana saja ke port lokal yang pernah dipakai berkomunikasi, tetapi ini makin jarang
  • Pada struktur server dan klien, masalahnya kecil karena perangkat di balik firewall cukup memulai koneksi lebih dulu
    • Dalam VPN, ini menjadi struktur hub-and-spoke di mana hub tidak berada di balik firewall dan spoke berada di balik firewall
  • Jika dua klien ingin berkomunikasi langsung, firewall di kedua sisi bisa saling memblokir
    • Keduanya harus lebih dulu mengirim keluar agar bisa menerima respons, tetapi lawannya berada dalam kondisi yang sama
    • Cara meminta pengguna membuka port secara manual tidak nyaman, dan skalabilitasnya rendah untuk jaringan mesh seperti Tailscale
    • Ada juga banyak firewall yang tidak bisa dikendalikan pengguna, seperti router di bandara atau kafe
  • Kunci penyelesaiannya adalah aturan firewall UDP tidak memverifikasi hubungan respons yang sebenarnya, melainkan hanya melihat kombinasi IP dan port
    • Jika kedua peer sudah mengetahui ip:port lawannya dan mengirim paket UDP secara bersamaan, beberapa paket awal mungkin diblokir tetapi state firewall akan terbuka
    • Setelah itu, paket yang dikirim lawan akan terlihat seperti respons dan bisa lewat
  • Pendekatan ini memerlukan side channel
    • Kedua endpoint harus mencoba berkomunikasi hampir pada saat yang sama
    • Cukup ada jalur komunikasi yang bisa menoleransi latensi beberapa detik dan hanya perlu membawa beberapa ribu byte
    • WebRTC memerlukan signaling channel, dan Tailscale menggunakan coordination server serta server DERP sebagai side channel
  • State firewall tidak permanen
    • Nilai umum timeout sesi UDP adalah 30 detik
    • Untuk menjaga koneksi tetap hidup, perlu mengirim paket secara berkala, atau memulai ulang koneksi dengan cara out-of-band saat diperlukan
  • Meski ada beberapa lapis firewall stateful, selama outbound diizinkan, metode pengiriman serentak tetap bisa menembusnya

Mengapa NAT membuat masalah ini lebih sulit

  • NAT (Network Address Translator) bekerja seperti firewall stateful sekaligus mengubah alamat IP atau port paket
  • Dalam NAT Traversal, yang terutama menjadi masalah adalah Source NAT (SNAT)
    • SNAT memungkinkan banyak perangkat berbagi jumlah alamat IP yang lebih sedikit, biasanya satu alamat IPv4 publik
    • DNAT juga ada, tetapi tidak terlalu terkait dengan masalah NAT Traversal yang dibahas di sini
  • Misalnya laptop mengirim paket UDP dari 192.168.0.20:1234 ke server internet 7.7.7.7:5678, router rumah akan memilih port kosong 2.2.2.2:4242 pada IP publiknya
    • Router membuat NAT mapping yang menyamakan 192.168.0.20:1234 dengan 2.2.2.2:4242
    • Setelah itu, paket keluar akan diubah seolah-olah berasal dari 2.2.2.2:4242
    • Respons yang masuk lalu diubah kembali ke 192.168.0.20:1234
  • Prinsip yang sama berlaku juga di jaringan perusahaan
    • Bedanya, lapisan NAT bisa terdiri dari beberapa perangkat karena kebutuhan high availability atau kapasitas, dan bisa memiliki beberapa IP publik

STUN dan penemuan NAT mapping

  • Peer di balik NAT tidak bisa mengetahui ip:port publiknya sendiri yang terlihat oleh lawan, dan NAT mapping biasanya baru dibuat ketika ada trafik keluar ke internet
  • STUN adalah protokol untuk mengetahui seperti apa klien di balik NAT terlihat dari internet
    • Klien bertanya ke server STUN, “endpoint-ku terlihat seperti apa olehmu?”
    • Server STUN merespons dengan ip:port publik tempat paket UDP itu datang
  • Jika ip:port publik yang diberitahukan STUN dibagikan ke peer, teknik pengiriman serentak yang digunakan untuk menembus firewall bisa diterapkan
  • Ini juga alasan logika NAT Traversal dan protokol komunikasi sebenarnya harus memakai soket yang sama
    • Setiap soket bisa mendapat mapping yang berbeda di perangkat NAT
    • Jika STUN dilakukan lewat soket lain, bukan soket yang akan dipakai untuk komunikasi sebenarnya, maka ip:port yang didapat tidak berguna
  • STUN saja tidak bisa menyelesaikan semua jenis NAT
    • Pada kebanyakan router rumahan, ini bisa bekerja
    • Pada beberapa gateway NAT perusahaan, ini bisa gagal
    • Asumsi bahwa 2.2.2.2:4242 yang terlihat lewat STUN memiliki arti yang sama untuk seluruh internet tidak selalu benar

NAT yang mudah dan NAT yang sulit

  • Perangkat NAT bisa membuat mapping yang berbeda tergantung tujuan, atau bisa juga mempertahankan mapping yang sama terlepas dari tujuan
  • RFC 4787 menyebut bentuk yang lebih mudah, yaitu mapping yang tetap sama tanpa bergantung pada tujuan, sebagai Endpoint-Independent Mapping (EIM)
  • Bentuk yang lebih sulit, yaitu mapping yang berubah tergantung tujuan, disebut Endpoint-Dependent Mapping (EDM)
    • Perubahannya bisa didasarkan hanya pada IP tujuan, atau pada kombinasi IP dan port tujuan
    • Dari sudut pandang NAT Traversal, keduanya sama-sama tidak menguntungkan
  • Istilah lama seperti Full Cone, Restricted Cone, Port-Restricted Cone, dan Symmetric NAT mencampurkan perilaku NAT mapping dan perilaku firewall dalam satu klasifikasi
    • Dalam implementasi praktis, pembedaan “Symmetric versus sisanya” atau EIM versus EDM lebih penting
  • Teknik pengiriman serentak dapat menembus berbagai bentuk firewall
    • Di lingkungan nyata, firewall yang bergantung pada IP dan port jauh lebih dominan
    • Namun jika ada satu saja hard NAT di suatu titik pada jalur, STUN dan pengiriman serentak saja tidak akan cukup dan masalah tetap muncul

Relay saat koneksi langsung gagal

  • Koneksi langsung bisa gagal meski semua teknik sudah digunakan
    • Pada jaringan dengan NAT yang sulit, atau jaringan yang memblokir outbound UDP selain DNS seperti guest Wi-Fi UC Berkeley, masalah ini tidak bisa diselesaikan dengan teknik NAT
  • Dalam kasus ini, paket dapat dipertukarkan melalui relay yang bisa diakses oleh kedua sisi
    • Memang tidak sebaik koneksi langsung, tetapi jika relay cukup dekat dengan rute dan memiliki bandwidth yang memadai, penurunan kualitas koneksi mungkin tidak terlalu besar
    • Walaupun latensi bertambah atau bandwidth berkurang, itu tetap lebih baik daripada tidak ada koneksi sama sekali
  • Protokol relay tradisional adalah TURN
    • Klien melakukan autentikasi ke server TURN
    • Server TURN mengalokasikan ip:port untuk relay
    • Peer berkomunikasi melalui ip:port tersebut
  • Tailscale membuat DERP(Detoured Encrypted Routing Protocol) sebagai pengganti TURN
    • DERP berjalan di atas HTTP
    • Berguna pada jaringan dengan aturan outbound yang ketat
    • Meneruskan payload terenkripsi berdasarkan kunci publik tujuan
  • DERP menjalankan dua peran
    • Relay data saat NAT Traversal gagal
    • Side channel yang membantu NAT Traversal
  • Diperkirakan bahwa dengan mengimplementasikan STUN, simultaneous send, dan relay, lebih dari 90% koneksi dapat dilakukan secara langsung, dan relay selalu bisa menjamin konektivitas dalam bentuk tertentu

Teknik tambahan untuk hard NAT

  • Pada hard NAT, peer yang lebih mudah tidak tahu port mana yang telah dibuka oleh NAT di sisi yang sulit
    • Dengan STUN, umumnya bisa diasumsikan bahwa IP-nya sudah benar
    • Yang tidak diketahui adalah port-nya, dan ada 65.535 kemungkinan nilai
  • Jika semua port dipindai satu per satu, pada 100 paket/detik, dalam kasus terburuk akan memakan waktu sekitar 10 menit, dan terlihat seperti port scan
  • Dengan memanfaatkan paradoks ulang tahun, biaya pencarian bisa dikurangi
    • Di sisi hard NAT, buka 256 port dengan 256 soket, lalu di sisi easy NAT telusuri port tujuan secara acak
    • Jika diasumsikan ada 256 port yang terbuka, probabilitas keberhasilannya adalah sebagai berikut
      • 174 pencarian acak: 50%
      • 256 pencarian acak: 64%
      • 1024 pencarian acak: 98%
      • 2048 pencarian acak: 99,9%
    • Pada 100 port/detik, setengahnya akan berhasil dalam 2 detik, dan sekitar 20 detik sudah cukup untuk hampir pasti berhasil meski hanya menelusuri kurang dari 4% dari seluruh ruang
  • Jika kedua sisi sama-sama hard NAT, situasinya jauh lebih sulit
    • Kini pasangan {source port, destination port} harus cocok
    • Dalam kondisi yang sama, probabilitas berhasil setelah 20 detik hanya 0,01%
    • Untuk probabilitas keberhasilan 99,9%, kedua sisi masing-masing harus mengirim 170.000 probe, dan pada 100 paket/detik itu membutuhkan 28 menit
  • Metode ini dapat meningkatkan konektivitas pada skenario home-office, home-cloud, serta sebagian office-cloud atau cloud-cloud
    • Router rumah cenderung merupakan easy NAT, sedangkan hard NAT cenderung berupa router kantor atau gateway NAT cloud

Protokol pemetaan port

  • Ada protokol yang langsung meminta ke NAT: “teruskan port WAN ini ke LAN ip:port ini”
  • Tiga yang paling umum adalah sebagai berikut
    • UPnP IGD: protokol dari akhir 1990-an yang menggunakan teknologi seperti XML, SOAP, dan multicast HTTP di atas UDP, sehingga implementasi dan keamanannya rumit
    • NAT-PMP: NAT Port Mapping Protocol buatan Apple yang hanya melakukan port forwarding dan lebih sederhana
    • PCP: bentuk lanjutan NAT-PMP v2 yang berkembang menjadi Port Control Protocol
  • Dengan mencoba UPnP IGD, NAT-PMP, dan PCP pada default gateway lokal, jika ada respons maka pemetaan port publik bisa diminta
    • Jika berhasil, kita bukan hanya bisa mengetahui ip:port publik seperti pada STUN, tetapi juga bisa membuat NAT bertindak lebih longgar terhadap port tersebut
    • Paket yang datang ke port yang dipetakan, dari mana pun asalnya, akan diteruskan ke perangkat internal
  • Protokol-protokol ini tidak bisa dijadikan andalan
    • Mungkin tidak diimplementasikan pada perangkat
    • Mungkin dinonaktifkan secara default
    • Mungkin dinonaktifkan karena kebijakan
  • Karena kerentanan UPnP di masa lalu, ada kasus di mana fitur ini dimatikan lewat kebijakan
    • Beberapa perangkat bahkan mematikan UPnP, NAT-PMP, dan PCP sekaligus dengan satu kotak centang “UPnP”
  • Jika bisa digunakan, satu NAT pada jalur data pada dasarnya seolah hilang sehingga koneksi jadi lebih mudah

Double NAT dan CGNAT

  • Pada double NAT, yaitu ketika ada dua lapis NAT di depan satu perangkat, perilaku NAT terluar, yakni NAT tepat sebelum internet, adalah yang paling penting
    • Seperti beberapa lapis stateful firewall, lapisan NAT tambahan umumnya tidak terlihat
    • Teknik yang ada dapat bekerja tanpa bergantung pada jumlah lapisan NAT
  • Hal yang paling terganggu oleh double NAT adalah protokol pemetaan port
    • Pemetaan port bekerja pada lapisan NAT yang paling dekat dengan klien
    • Namun yang harus dilalui peer jarak jauh adalah NAT paling luar
    • Akibatnya, ip:port yang didapat adalah alamat jaringan perantara yang tidak bisa dijangkau oleh peer jarak jauh
  • Double NAT tidak terlihat oleh sebagian besar aplikasi umum yang tidak melakukan NAT Traversal secara eksplisit
    • Tetapi ini bisa memperburuk multiplayer pada banyak game, dan bisa menghilangkan IPv6 sehingga mengurangi opsi koneksi tanpa NAT
  • CGNAT(Carrier-Grade NAT) adalah struktur di mana ISP menerapkan SNAT sekali lagi untuk mengatasi kekurangan alamat IPv4
    • Router rumah melakukan SNAT pada perangkat ke IP perantara
    • Lapisan NAT kedua di dalam jaringan ISP memetakan IP-IP perantara tersebut ke lebih sedikit IP publik
  • Pada CGNAT, pengguna tidak dapat mereset NAT milik ISP
    • Dulu pengguna tingkat lanjut bisa menghindari masalah dengan port forwarding pada router rumah, tetapi pada CGNAT cara itu terhalang
  • Karena CGNAT pada dasarnya juga double NAT, sebagian besar teknik yang ada tetap bekerja
    • Protokol pemetaan port menjadi pengecualian karena memiliki keterbatasan

Masalah hairpinning

  • Dua peer yang berada di belakang CGNAT yang sama tetapi di belakang home NAT yang berbeda menghadapi masalah khusus
    • Server STUN memberi tahu ip:port publik sebagaimana terlihat dari luar internet
    • Namun yang sebenarnya dibutuhkan kedua peer adalah ip:port yang berlaku di jaringan perantara di dalam CGNAT
  • Jika salah satu home NAT mendukung protokol pemetaan port, koneksi bisa menjadi lebih mudah
    • Karena double NAT, justru berguna bahwa protokol pemetaan port memberi tahu ip:port dari jaringan perantara
  • Jika pemetaan port tidak dapat digunakan, maka hairpinning diperlukan
    • Misalnya peer A mengirim paket ke 2.2.2.2:5678 milik peer B yang diperoleh melalui STUN
    • CGNAT seharusnya tidak mengirim paket ini ke internet luar, melainkan memutarnya kembali di dalam ke pemetaan NAT milik peer B
  • Banyak NAT tidak mendukung hairpinning
    • Ada perangkat yang berasumsi bahwa paket dari jaringan internal menuju IP non-internal selalu keluar ke internet
    • Asumsi seperti ini kadang tertanam di routing silicon dan mungkin tidak bisa diperbaiki tanpa hardware baru
  • Saat CGNAT terlibat, hairpinning menjadi penting untuk konektivitas
    • Jika hairpinning dan pemetaan port sama-sama gagal, maka harus menggunakan relay

IPv6 dan NAT64

  • Dalam dunia yang hanya memiliki IPv6, masalah NAT menjadi jauh lebih sederhana
    • Semua perangkat bisa memiliki alamat yang dapat dijangkau tanpa NAT
    • Namun firewall stateful tetap ada, jadi penembusan firewall dan side channel masih diperlukan
    • Fallback relay yang menggunakan protokol seperti HTTP juga tetap berguna untuk jaringan yang memblokir UDP keluar
  • IPv6 saja masih belum cukup
    • Dunia masih didominasi IPv4 dan sekitar 33% menggunakan IPv6
    • Implementasi IPv6 tidak merata, sehingga tergantung kombinasi peer bisa saja 100% IPv6, atau 0% IPv6
    • Jika tujuannya adalah koneksi tanpa syarat, penanganan IPv4+NAT tetap harus dilakukan
  • Koeksistensi IPv6 dan IPv4 menciptakan kasus tambahan bernama NAT64
    • NAT44 menerjemahkan IPv4 ke IPv4 lain
    • NAT64 menerjemahkan IPv6 internal ke IPv4 eksternal
    • Jika digunakan bersama DNS64, ini dapat memberi akses ke internet IPv4 sambil tampak seperti jaringan IPv6-only bagi perangkat
  • Aplikasi yang hanya menggunakan nama DNS hampir tidak perlu menyadari keberadaan NAT64
    • Namun NAT Traversal menangani IP dan port spesifik secara langsung, jadi perlu penanganan terpisah
  • Jika perangkat mendukung CLAT (Customer-side translator), sistem operasi akan membuatnya tampak seolah memiliki koneksi IPv4 langsung dan menangani NAT64 di belakang layar
    • CLAT umum pada perangkat seluler
    • Jarang pada desktop, laptop, dan server
  • Jika tidak ada CLAT, NAT64+DNS64 harus dideteksi secara langsung
    • Kirim permintaan DNS ke ipv4only.arpa.
    • Nama ini hanya di-resolve ke alamat IPv4 tetap yang sudah dikenal
    • Jika alamat IPv6 dikembalikan, berarti itu hasil terjemahan DNS64 sehingga prefix NAT64 dapat diketahui
  • Setelah itu, untuk berkomunikasi dengan alamat IPv4, cukup kirim paket IPv6 ke {NAT64 prefix + IPv4 address}
    • Jika STUN dijalankan melalui NAT64 untuk menemukan ip:port publik, masalahnya kembali menjadi NAT Traversal biasa

Menggabungkan jalur kandidat dengan ICE

  • Pendekatan yang mencoba mengklasifikasikan secara tepat sebelumnya teknik mana yang harus dipakai dari semua opsi yang ada tidak skalabel
    • Karena network engineer dan implementator perangkat NAT menciptakan beragam perilaku
  • Inti dari ICE (Interactive Connectivity Establishment) adalah algoritme yang mencoba semua kemungkinan secara bersamaan, lalu memilih jalur terbaik di antara yang berhasil
  • Saat komunikasi dimulai, kumpulkan daftar endpoint kandidat untuk soket lokal
    • IPv6 ip:ports
    • IPv4 LAN ip:ports
    • IPv4 WAN ip:ports yang ditemukan lewat STUN
    • IPv4 WAN ip:ports yang ditemukan lewat translator NAT64
    • IPv4 WAN ip:port yang dialokasikan oleh protokol pemetaan port
    • Endpoint yang disediakan operator seperti port forwarding yang dikonfigurasi statis
  • Setelah itu, tukarkan daftar kandidat melalui side channel, lalu kirim paket probe ke semua endpoint yang diberikan pihak lawan
    • Paket probe berfungsi sebagai paket untuk membuka firewall dan NAT
    • Sekaligus berfungsi sebagai pemeriksaan status model ping/pong
  • Setelah jangka waktu tertentu, pilih jalur kandidat terbaik secara heuristik di antara yang terbukti berfungsi
    • ICE biasanya memakai skor bawaan seperti LAN > WAN > WAN+NAT
    • Sejak v0.100.0, Tailscale menggunakan round-trip latency alih-alih urutan preferensi yang di-hardcode
  • Tailscale tidak membagi koneksi secara ketat menjadi tahap probe dan tahap komunikasi
    • Semua koneksi dimulai dengan DERP yang sudah dipilih lebih dulu
    • Pengguna bisa langsung memakai koneksi melalui jalur fallback
    • Penjelajahan jalur berjalan paralel, dan jika beberapa detik kemudian ditemukan jalur yang lebih baik, koneksi di-upgrade secara transparan

Pemeliharaan jalur dan keamanan saat operasi

  • Perlu berhati-hati terhadap jalur asimetris
    • ICE berusaha agar kedua peer memilih jalur jaringan yang sama sehingga aliran paket dua arah tetap terjaga
    • Meski tidak mengimplementasikan prosedur dengan tingkat yang sama, semua jalur yang digunakan tetap harus memiliki trafik dua arah
    • Probe ping/pong berkala saja sudah bisa mempertahankan hal ini
  • Jalur yang saat ini dipilih bisa gagal
    • Contohnya ketika status hilang karena pemeliharaan NAT
    • Semua jalur yang mungkin bisa terus di-probe untuk menjaga warm fallback
    • Namun karena downgrade jarang terjadi, sering kali lebih efisien untuk turun ke relay upaya terakhir lalu memulai ulang penjelajahan jalur
  • Asumsi bahwa protokol lapisan atas menyediakan keamanannya sendiri sangat penting
    • QUIC menggunakan sertifikat TLS
    • WireGuard menggunakan kunci publiknya sendiri
  • Jika jalur diganti secara dinamis, keamanan berbasis IP menjadi tidak lagi bermakna
    • Minimal diperlukan autentikasi end-to-end
  • Jika ada keamanan end-to-end di lapisan atas, maka walaupun probe ping/pong bisa di-spoof, skenario terburuknya hanya penyerang dapat mengarahkan trafik agar melewati dirinya
    • Meski begitu, paket penjelajahan jalur juga sebaiknya diautentikasi dan dienkripsi

Komponen NAT Traversal yang tangguh

  • NAT Traversal yang tangguh memerlukan elemen-elemen berikut
    • Protokol berbasis UDP yang akan diperluas
    • Soket yang dapat diakses langsung dari dalam program
    • Side channel untuk berkomunikasi dengan peer
    • Beberapa server STUN
    • Opsional, tetapi sangat disarankan, jaringan fallback relay
  • Langkah-langkah pelaksanaannya adalah sebagai berikut
    • Enumerasi semua ip:ports soket pada antarmuka yang terhubung langsung
    • Query server STUN untuk menemukan WAN ip:ports dan tingkat kesulitan NAT
    • Cari WAN ip:ports tambahan dengan protokol pemetaan port
    • Jika ada NAT64, deteksi itu dan temukan juga WAN ip:port melalui jalur tersebut
    • Tukarkan semua ip:ports dan kunci enkripsi dengan peer melalui side channel
    • Untuk pembentukan koneksi yang cepat, komunikasi bisa dimulai lebih dulu melalui fallback relay
    • Lakukan probe ke semua ip:ports milik lawan, dan bila perlu lakukan penjelajahan berbasis paradoks ulang tahun untuk menembus hard NAT
    • Jika ditemukan jalur koneksi yang lebih baik daripada jalur saat ini, lakukan upgrade secara transparan
    • Jika jalur aktif berhenti, lakukan downgrade seperlunya untuk mempertahankan konektivitas
    • Semua komunikasi harus dienkripsi dan diautentikasi secara end-to-end

1 komentar

 
GN⁺ 2025-01-06
Opini Hacker News
  • Tulisan yang bagus. Ada semacam pengetahuan implisit yang umum bahwa hole punching berbasis TCP sebaiknya tidak dilakukan karena lebih sulit daripada UDP, tetapi dalam praktiknya, dibandingkan alur UDP yang sudah kompleks, kompleksitas tambahannya tampaknya tidak besar
    Tulisan itu juga mengakui bahwa traversal NAT TCP memang mungkin, tetapi menambah kompleksitas, dan jika masuk lebih dalam mungkin memerlukan modifikasi kernel. Namun menurut saya, bagian yang memulai koneksi dengan paket UDP mentah cukup diganti dengan paket TCP SYN dan dukungan simultaneous open
    Terutama mengingat ada jaringan seperti Wi‑Fi tamu UC Berkeley yang memblokir semua pengiriman UDP selain DNS, sayang jika TCP hole punching hanya dilewati begitu saja dengan alasan “lebih sulit daripada UDP”. Menurut saya ini hampir sama layaknya untuk diwujudkan, dengan kompleksitas tambahan yang terbatas
    https://ttcplinux.sourceforge.net/documents/one/tcpstate/tcp...

    • Karena ada stateful firewall, dan sebagian besar filter NAT adalah EDF, bukan EIF, pada UDP pun simultaneous open, yakni pengiriman serentak, tetap diperlukan
      Jadi kompleksitas tambahan untuk melakukan simultaneous open dengan TCP cukup kecil. Kesulitan utamanya adalah menyampaikan mapping publik dan mengoordinasikan punching/opening secara “serentak”, dan ini biasanya juga diperlukan pada UDP
      Satu hal yang lebih rumit di TCP adalah kita perlu melakukan pemanggilan connect() sungguhan, alih-alih membuat paket TCP SYN palsu. Sebab sebagian firewall memeriksa nomor urut
    • Poin yang sangat bagus. Saya pernah mengimplementasikan TCP hole punching sendiri dan sekarang punya implementasi yang cukup baik; keuntungan besar memakai TCP adalah setelah lubang terbuka, kita tidak perlu menaruh ulang TCP versi miskin di atas UDP
      Namun TCP hole punching bisa terlihat jauh lebih mirip SYN flood daripada paket UDP, sehingga tingkat keberhasilannya bisa lebih rendah di sebagian jaringan. Dalam praktiknya, saya belum banyak melihat pemfilteran
      TCP hole punching cukup menarik. Implementasinya menghitung “offset jam”, yaitu seberapa jauh jam sistem meleset dari NTP, melalui beberapa pengukuran NTP, lalu pihak pemulai menentukan waktu pertemuan di masa depan berdasarkan NTP. Ini lebih akurat dari dugaan, dan TCP hole punching juga bekerja antar-socket pada antarmuka yang sama
      Alasan mendukung mode punching lokal yang aneh seperti ini adalah, jika punching di dalam host berhasil dengan efisiensi sebesar itu, kemungkinan besar di LAN dan internet pun cukup cepat. Kodenya menggunakan Python, dan percobaan pertama cukup mengejutkan. Karena TCP hole punching sensitif terhadap timing, kegagalan terjadi ketika saya memakai pengelolaan socket langsung gaya lama di Python, threading, dan event loop seadanya yang dibuat berdasarkan pengalaman socket C
      Agar kode itu berjalan, prioritas proses Python harus dinaikkan supaya proses lain tidak menimbulkan jeda di antara upaya punching. Pada implementasi yang tidak efisien, ia memang sesensitif itu terhadap waktu. Implementasi saat ini memakai pool proses yang masing-masing memiliki event loop sendiri, membuat daftar pekerjaan yang tersebar dalam waktu, lalu tiap pekerjaan membuka koneksi dengan menggunakan ulang socket yang sama. Setelah diuji di sistem operasi utama, saya menilai pendekatan ini yang paling baik untuk Python
      Saya setuju bahwa tingkat kesulitan TCP dan UDP hole punching mirip. Pada keduanya, bagian tersulit adalah tahap prediksi NAT. Saya belum memakai kode untuk menembus NAT simetris, tetapi mulai terlihat cara untuk mengintegrasikannya atau menjadikannya plugin baru
    • Saya terpikir satu kelemahan lain TCP punching dibanding UDP. Pada TCP, router harus mencatat status koneksi
      Tabel status router sangat kecil, dan sebagian teknik punching cukup agresif. Misalnya, jika membuka ratusan koneksi TCP seperti algoritma yang mencoba menembus NAT simetris, router bisa saja dibuat berada dalam kondisi denial of service
      Berkat optimisasi pengelolaan status, UDP mungkin lebih kecil kemungkinannya membuat seluruh router macet akibat punching. Namun ini hanya dugaan
  • Efeknya menarik karena cukup bagus, tetapi entah kenapa jadi terasa mengkhawatirkan kalau ada yang mengusulkan memasukkan ini ke jaringan perusahaan produksi
    Rasanya seperti melewati NAT dan firewall tradisional, lalu sebagai gantinya hanya bergantung pada satu ACL perangkat lunak, sehingga terlihat berisiko. Misalnya, jika ada Tailscale di VM yang terbengkalai di lingkungan pengujian AWS dan penyerang mendapat akses ke sana, tampaknya akan terbentuk jalur hingga laptop di jaringan internal perusahaan, melewati kernel, di mana hanya kode ACL Tailscale di ruang pengguna yang menentukan boleh/tidaknya akses
    Tidak tahu apakah kita bisa mengetahui jika seseorang yang tidak berwenang berhasil masuk sampai titik itu

    • Karena itu banyak orang terus mengulang bahwa NAT bukan mekanisme keamanan
      Menembus NAT dan sebagian besar filter pelacakan status yang terkait dengannya sangat mudah. Saya pernah mengimplementasikan hal semacam ini sebagai produk jualan di lingkungan produksi perusahaan sungguhan; ini bukan sihir, melainkan teknik yang sudah dikenal baik oleh para praktisi
      Jika menginginkan penyaringan paket yang sebenarnya, yaitu firewall, Anda harus menempatkan instance firewall terpisah dari NAT dan menetapkan aturan yang tepat. Namun itu pun terutama hanya membantu mengurangi volume lalu lintas; manfaat keamanan nyata dari firewall itu sendiri kini kecil. Sebab sebagian besar serangan masuk melalui lapisan yang lebih tinggi seperti HTTP/HTTPS, POP/IMAP
    • Agar adil, alasan semua orang keliru menganggap NAT sebagai mekanisme keamanan adalah karena secara tradisional NAT diterapkan bersama firewall pelacakan status
      Pada praktiknya firewall pelacakan statuslah yang melakukan sebagian besar pekerjaan, tetapi NAT yang mendapat kreditnya. Tailscale tidak menghilangkan firewall, melainkan menyediakan konfigurasi berbasis ACL yang benar dan jauh lebih menyeluruh
      Namun saya mengakui bahwa alat ACL Tailscale masih punya ruang besar untuk diperbaiki
    • Networking sudah sejak lama menjadi semacam tempat pembuangan limbah beracun untuk keamanan dan salah konfigurasi. Kini ditambah lagi dengan model networking berbasis host modern untuk container
      Dampaknya, stack jaringan Windows juga berubah cukup banyak dan menjadi lebih kompleks. Sejak WireGuard masuk ke Linux, semua orang tampaknya punya setidaknya satu VPN yang terhubung ke VPS di suatu tempat. Karena kita tidak tahu apa yang tidak kita ketahui, situasi sebenarnya kemungkinan lebih buruk dari yang dibayangkan
    • Ini adalah untuk NAT traversal, yaitu perangkat yang dibuat untuk mengakali kelangkaan alamat IPv4
      Firewall adalah konsep yang berbeda. Namun jika mengaitkan konektivitas dan keamanan, menyedihkan sekaligus mengkhawatirkan bahwa keamanan internet selalu bergantung pada cara memblokir paket berdasarkan port tujuan
      Kenyataannya, kita melakukan hal yang mudah alih-alih yang benar, tetapi tetap diberi label “solusi profesional”
    • VoIP sejak dulu bekerja dengan cara seperti ini, dan ada banyak infrastruktur standar terbuka untuk memudahkannya. Contohnya ICE, TURN
      Meski begitu, sesuatu di dalam jaringan tetap harus lebih dulu menghubungi pihak luar, sehingga firewall yang sebenarnya harus mengelola daftar izin untuk koneksi keluar maupun masuk
      Dengan kata lain, jika bergantung pada keamanan perimeter, hanya soal waktu sampai seseorang akhirnya menemukan apa versi “rompi reflektif” di organisasinya sendiri
  • Akan menyenangkan jika ada alternatif mirip Tailscale tanpa enkripsi koneksi untuk perangkat yang sudah melakukan enkripsi di lapisan aplikasi. Seperti hampir seluruh internet bekerja, tidak selalu perlu mengenkripsi sampai lapisan bawah
    Pada perangkat berdaya rendah, misalnya perangkat IoT yang menjalankan tunnel mirip Tailscale, biaya komputasinya sangat besar
    Tunnel GRE memang ada dan banyak dipakai, tetapi karena UDP hole punching tidak ditangani, diperlukan struktur hub-and-spoke. Dengan GRE, yaitu ip fou, kita tidak bisa membuat mesh antarrekan
    Saya penasaran apakah ada library yang, setelah handshake kriptografis untuk verifikasi identitas, menyediakan UDP hole punching dan tunnel GRE yang tidak terenkripsi

    • Standar yang mapan di bidang ini adalah ICE(Interactive Connectivity Establishment), yang menjadi dasar WebRTC. Ada beberapa library bagus yang mengimplementasikannya atau mengimplementasikan sebagian elemennya
      Jika menginginkan sesuatu yang lebih cocok untuk konektivitas umum, libp2p mungkin mendekati yang Anda cari
      https://datatracker.ietf.org/doc/html/rfc8445
      https://github.com/pion/webrtc
      https://github.com/algesten/str0m
      https://libp2p.io
    • Bukan UDP, tetapi saya mengimplementasikan TCP hole punching dan metode NAT traversal utama lainnya di sini: https://github.com/robertsdotpm/p2pd
      Ditulis dengan Python. Namun, seperti kebanyakan kode jaringan, ini tidak mengasumsikan penggunaan antarmuka default. Saya ingin membuatnya lebih beragam dan berguna dengan memungkinkan layanan dijalankan di antarmuka apa pun yang diinginkan
      Sebagian besar berbasis modul standard library. Saya tidak suka ekstensi C karena sering merusak paket lintas platform
    • Karena TURN, STUN, dan ICE-lah yang melakukan hole punching di VoIP, library dari sana bisa digunakan ulang
    • Bisa juga mencoba menghidupkan kembali Teredo
  • Melihat bagian bahwa para peer harus mengetahui ip:port yang dipakai pihak lain sebelumnya, dan bahwa server koordinasi dibuat untuk menyinkronkannya, saya jadi berharap SIP benar-benar sesuai dengan namanya
    SIP adalah Session Initiation Protocol, jadi dari namanya seharusnya juga bisa memulai sesi arbitrer seperti VPN, tetapi pada praktiknya terlalu kompleks dan kacau sehingga nilainya untuk ditanggung menjadi kecil. Saya menganggapnya awalnya dibuat sebagai side channel komunikasi untuk membangun stream RTP P2P

    • SIP melakukan terlalu banyak hal sampai menakutkan untuk memuat semuanya di kepala sekaligus
      Mirip HTTP, tetapi stateful, dua arah, federatif, dan juga berjalan di atas UDP
      Melihat banyaknya hal yang harus diimplementasikan baresip hanya untuk mendukung SIP, termasuk TLS over UDP, jumlahnya luar biasa. Bahkan itu bukan karena bloat; fitur-fitur tersebut memang benar-benar diperlukan
  • Ini adalah tulisan dari tahun 2020. Diskusi sebelumnya sebagai berikut
    2022: https://news.ycombinator.com/item?id=30707711
    2020: https://news.ycombinator.com/item?id=24241105

  • Ini adalah tulisan yang biasa saya kirimkan ke orang-orang saat menjelaskan NAT traversal
    Saat kita membuat aplikasi P2P, mungkin kita akan terus bergantung pada cara ini. IPv6 tidak mendapatkan momentum yang cukup, dan NAT serta SNI routing menyelesaikan sebagian besar masalah bagi kebanyakan orang
    Dari sisi ISP juga tidak banyak insentif untuk membuat situasi itu berubah

  • Menurut saya ini termasuk salah satu tulisan paling mendetail di seluruh internet tentang NAT traversal. Namun, informasi tentang perilaku delta tidak ada
    Ini bukan hal yang rumit; maksudnya, sebagian NAT memiliki pola yang bisa diamati saat menetapkan port eksternal yang berurutan. Pola paling umum adalah mempertahankan port sumber, dan bisa juga ada pola seperti menaikkan 1 dari mapping sebelumnya
    Secara teori ini tulisan yang sangat bagus, tetapi saya penasaran sejauh mana software engineer bisa benar-benar memanfaatkannya. Tulisan ini menjelaskan banyak hal, tetapi mungkin tidak cukup rinci untuk menulis algoritme. Misalnya, saya tidak yakin apakah hanya dengan membaca tulisan ini seseorang bisa menulis algoritme untuk menguji tipe NAT atau menyesuaikan kode hole punching miliknya sendiri
    Secara pribadi, saya pernah melihat beberapa paper yang tabel sederhananya lebih berguna daripada tulisan sepanjang ini. Meski begitu, ini bisa menjadi titik awal yang baik
    Bagian terakhir tulisan ini sangat penting. Ada kemungkinan untuk melewati symmetric NAT yang digunakan pada sistem mobile. Riset NAT traversal terbaru juga memakai teknik serupa dan mengklaim tingkat keberhasilan hampir 100%

  • Tulisan menarik yang mengingatkan pada masa lalu. Pada 2010, saya membuat oblivious P2P mesh network yang menggunakan cara seperti ini
    Saat itu orang-orang tidak terlalu peduli soal keamanan seperti yang kami bayangkan, dan sekarang pun masih belum cukup peduli. Perangkat makin banyak dan nilainya makin besar, tetapi tetap saja cukup tidak aman
    Hardware root of trust, rantai kepercayaan yang aman untuk autentikasi/otorisasi, serta endpoint yang benar-benar aman dengan hak sementara seminimal mungkin masih sulit, dan teater keamanan perimeter jaringan masih terus berlangsung di jaringan rumah, jaringan perusahaan, maupun jaringan data center produksi skala besar
    Satu-satunya alasan hal-hal ini tidak tampak sebagai akar penyebab utama pelanggaran keamanan adalah karena masih ada begitu banyak jalur serangan yang lebih mudah

  • Sedikit keluar dari topik, tetapi beberapa minggu lalu saya membaca sedikit tentang bidang ini dari posisi benar-benar tidak tahu apa-apa
    Kesan yang saya dapat adalah IPv6 akan menyingkirkan semua ini dan membuat NAT traversal tidak lagi diperlukan. Kalau begitu, saya penasaran mengapa IPv6 tidak digunakan lebih luas, dan bagaimana cara memulainya di jaringan rumah serta Tailscale VPN

    • Saya tidak tahu seberapa besar salah satu alasan IPv6 kurang populer ini, tetapi fakta bahwa sulit digunakan manusia selalu menjadi tantangan
      Insentif bisnis juga kurang
  • Fakta bahwa hal seperti ini muncul alih-alih IPv6 benar-benar menunjukkan kekuatan hack yang cukup baik