Menggunakan SO_REUSEADDR dan SO_EXCLUSIVEADDRUSE

Mengembangkan infrastruktur jaringan tingkat tinggi yang aman adalah prioritas bagi sebagian besar pengembang aplikasi jaringan. Namun, keamanan soket sering diabaikan meskipun sangat penting ketika mempertimbangkan solusi yang sepenuhnya aman. Keamanan soket, khususnya, menangani proses yang mengikat ke port yang sama yang sebelumnya terikat oleh proses aplikasi lain. Di masa lalu, dimungkinkan bagi aplikasi jaringan untuk "membajak" port aplikasi lain, yang dapat dengan mudah menyebabkan serangan "penolakan layanan" atau pencurian data.

Secara umum, keamanan soket berlaku untuk proses sisi server. Lebih khusus lagi, keamanan soket berlaku untuk aplikasi jaringan apa pun yang menerima koneksi dan menerima lalu lintas datagram IP. Aplikasi ini biasanya mengikat port terkenal dan merupakan target umum untuk kode jaringan berbahaya.

Aplikasi klien lebih kecil kemungkinannya menjadi target serangan tersebut - bukan karena kurang rentan, tetapi karena sebagian besar klien mengikat port lokal "sementara" daripada port "layanan" statis. Aplikasi jaringan klien harus selalu mengikat port ephemeral (dengan menentukan port 0 dalam struktur SOCKADDR yang ditunjukkan oleh parameter nama saat memanggil fungsi ikat ) kecuali ada alasan arsitektur yang menarik untuk tidak. Port lokal ephemeral terdiri dari port yang lebih besar dari port 49151. Sebagian besar aplikasi server untuk layanan khusus yang mengikat port khusus terkenal yang kurang dari atau sama dengan port 49151. Jadi untuk sebagian besar aplikasi, biasanya tidak ada konflik untuk permintaan ikatan antara aplikasi klien dan server.

Bagian ini menjelaskan tingkat keamanan default pada berbagai platform Microsoft Windows dan bagaimana opsi soket tertentu SO_REUSEADDR dan SO_EXCLUSIVEADDRUSE berdampak dan memengaruhi keamanan aplikasi jaringan. Fitur tambahan yang disebut keamanan soket yang ditingkatkan tersedia di Windows Server 2003 dan yang lebih baru. Ketersediaan opsi soket ini dan keamanan soket yang ditingkatkan bervariasi di seluruh versi sistem operasi Microsoft, seperti yang ditunjukkan pada tabel di bawah ini.

Platform SO_REUSEADDR SO_EXCLUSIVEADDRUSE Keamanan soket yang ditingkatkan
Windows 95 Tersedia Tidak Tersedia Tidak Tersedia
Windows 98 Tersedia Tidak Tersedia Tidak Tersedia
Windows Me Tersedia Tidak Tersedia Tidak Tersedia
Windows NT 4.0 Tersedia Tersedia dalam Paket Layanan 4 dan yang lebih baru Tidak Tersedia
Windows 2000 Tersedia Tersedia Tidak Tersedia
Windows XP Tersedia Tersedia Tidak Tersedia
Windows Server 2003 Tersedia Tersedia Tersedia
Windows Vista Tersedia Tersedia Tersedia
Windows Server 2008 Tersedia Tersedia Tersedia
Windows 7 dan yang lebih baru Tersedia Tersedia Tersedia

Menggunakan SO_REUSEADDR

Opsi soket SO_REUSEADDR memungkinkan soket untuk mengikat secara paksa ke port yang digunakan oleh soket lain. Soket kedua memanggil setsockopt dengan parameter optname diatur ke SO_REUSEADDR dan parameter optval diatur ke nilai boolean TRUE sebelum memanggil bind pada port yang sama dengan soket asli. Setelah soket kedua berhasil diikat, perilaku untuk semua soket yang terikat ke port tersebut tidak ditentukan. Misalnya, jika semua soket pada port yang sama menyediakan layanan TCP, setiap permintaan koneksi TCP yang masuk melalui port tidak dapat dijamin untuk ditangani oleh soket yang benar - perilakunya tidak deterministik. Program berbahaya dapat menggunakan SO_REUSEADDR untuk mengikat soket secara paksa yang sudah digunakan untuk layanan protokol jaringan standar untuk menolak akses ke layanan tersebut. Tidak ada hak istimewa khusus yang diperlukan untuk menggunakan opsi ini.

Jika aplikasi klien mengikat ke port sebelum aplikasi server dapat mengikat ke port yang sama, maka masalah dapat diakibatkan. Jika aplikasi server secara paksa mengikat menggunakan opsi soket SO_REUSEADDR ke port yang sama, maka perilaku untuk semua soket yang terikat ke port tersebut tidak ditentukan.

Pengecualian untuk perilaku non-deterministik ini adalah soket multicast. Jika dua soket terikat ke antarmuka dan port yang sama dan merupakan anggota grup multicast yang sama, data akan dikirimkan ke kedua soket, bukan yang dipilih secara acak.

Menggunakan SO_EXCLUSIVEADDRUSE

Sebelum opsi soket SO_EXCLUSIVEADDRUSE diperkenalkan, sangat sedikit yang dapat dilakukan pengembang aplikasi jaringan untuk mencegah program berbahaya mengikat port tempat aplikasi jaringan terikat. Untuk mengatasi masalah keamanan ini, Windows Sockets memperkenalkan opsi soket SO_EXCLUSIVEADDRUSE , yang tersedia di Windows NT 4.0 dengan Paket Layanan 4 (SP4) dan yang lebih baru.

Opsi soket SO_EXCLUSIVEADDRUSE hanya dapat digunakan oleh anggota grup keamanan Administrator pada Windows XP dan yang lebih lama. Alasan mengapa persyaratan ini diubah pada Windows Server 2003 dan yang lebih baru dibahas nanti di artikel.

Opsi SO_EXCLUSIVEADDRUSE diatur dengan memanggil fungsi setsockopt dengan parameter optname diatur ke SO_EXCLUSIVEADDRUSE dan parameter optval diatur ke nilai boolean TRUE sebelum soket terikat. Setelah opsi diatur, perilaku panggilan ikatan berikutnya berbeda tergantung pada alamat jaringan yang ditentukan dalam setiap panggilan ikatan .

Tabel di bawah ini menjelaskan perilaku yang terjadi di Windows XP dan sebelumnya ketika soket kedua mencoba mengikat ke alamat yang sebelumnya diikat oleh soket pertama menggunakan opsi soket tertentu.

Catatan

Dalam tabel di bawah ini, "kartubebas" menunjukkan alamat wildcard untuk protokol yang diberikan (seperti "0.0.0.0" untuk IPv4 dan "::" untuk IPv6). "Spesifik" menunjukkan alamat IP tertentu yang ditetapkan antarmuka. Sel tabel menunjukkan apakah ikatan berhasil atau tidak ("Berhasil") atau kesalahan dikembalikan ("INUSE" untuk kesalahan WSAEADDRINUSE ; "ACCESS" untuk kesalahan WSAEACCES ).

Panggilan ikatan pertama Panggilan ikatan kedua
Default SO_REUSEADDR SO_EXCLUSIVEADDRUSE
Karakter kartubebas Spesifik Karakter kartubebas Spesifik Karakter kartubebas Spesifik
Default Karakter kartubebas INUSE INUSE Berhasil Berhasil INUSE INUSE
Spesifik INUSE INUSE Berhasil Berhasil INUSE INUSE
SO_REUSEADDR Karakter kartubebas INUSE INUSE Berhasil Berhasil INUSE INUSE
Spesifik INUSE INUSE Berhasil Berhasil INUSE INUSE
SO_EXCLUSIVEADDRUSE Karakter kartubebas INUSE INUSE ACCESS ACCESS INUSE INUSE
Spesifik INUSE INUSE ACCESS ACCESS INUSE INUSE

Ketika dua soket terikat ke nomor port yang sama tetapi pada antarmuka eksplisit yang berbeda, tidak ada konflik. Misalnya, dalam kasus di mana komputer memiliki dua antarmuka IP, 10.0.0.1 dan 10.99.99.99, jika panggilan pertama untuk mengikat adalah pada 10.0.0.1 dengan port diatur ke 5150 dan SO_EXCLUSIVEADDRUSE ditentukan, maka panggilan kedua untuk mengikat pada 10.99.99.99 dengan port juga diatur ke 5150 dan tidak ada opsi yang ditentukan yang akan berhasil. Namun, jika soket pertama terikat ke alamat wildcard dan port 5150, maka setiap panggilan ikatan berikutnya ke port 5150 dengan set SO_EXCLUSIVEADDRUSE akan gagal dengan WSAEADDRINUSE atau WSAEACCES yang dikembalikan oleh operasi pengikatan .

Dalam kasus di mana panggilan pertama ke set ikatanbaik SO_REUSEADDR atau tanpa opsi soket sama sekali, panggilan ikatan kedua akan "membajak" port dan aplikasi tidak akan dapat menentukan mana dari dua soket yang menerima paket tertentu yang dikirim ke port "bersama".

Aplikasi umum yang memanggil fungsi ikatan tidak mengalokasikan soket terikat untuk penggunaan eksklusif, kecuali opsi soket SO_EXCLUSIVEADDRUSE dipanggil pada soket sebelum panggilan ke fungsi ikat . Jika aplikasi klien mengikat port ephemeral atau port tertentu sebelum aplikasi server mengikat ke port yang sama, maka masalah dapat diakibatkan. Aplikasi server dapat secara paksa mengikat port yang sama dengan menggunakan opsi soket SO_REUSEADDR pada soket sebelum memanggil fungsi ikat , tetapi perilaku untuk semua soket yang terikat ke port tersebut kemudian tidak ditentukan. Jika aplikasi server mencoba menggunakan opsi soket SO_EXCLUSIVEADDRUSE untuk penggunaan port secara eksklusif, permintaan akan gagal.

Sebaliknya, soket dengan set SO_EXCLUSIVEADDRUSE tidak selalu dapat digunakan kembali segera setelah penutupan soket. Misalnya, jika soket mendengarkan dengan set SO_EXCLUSIVEADDRUSE menerima koneksi dan kemudian ditutup, soket lain (juga dengan SO_EXCLUSIVEADDRUSE) tidak dapat mengikat ke port yang sama dengan soket pertama sampai koneksi asli menjadi tidak aktif.

Masalah ini dapat menjadi rumit karena protokol transportasi yang mendasar mungkin tidak menghentikan koneksi meskipun soket telah ditutup. Bahkan setelah soket ditutup oleh aplikasi, sistem harus mengirimkan data yang di-buffer, mengirim pesan pemutusan sambungan dengan anggun ke serekan, dan menunggu pesan pemutusan sambungan yang sesuai dari serekan. Ada kemungkinan bahwa protokol transportasi yang mendasar mungkin tidak pernah melepaskan koneksi; misalnya, serekan yang berpartisipasi dalam koneksi asli mungkin mengiklankan jendela ukuran nol, atau beberapa bentuk konfigurasi "serangan" lainnya. Dalam kasus seperti itu, koneksi klien tetap dalam keadaan aktif meskipun permintaan untuk menutupnya, karena data yang tidak diakui tetap berada di buffer.

Untuk menghindari situasi ini, aplikasi jaringan harus memastikan pematian yang lancar dengan memanggil matikan dengan bendera SD_SEND diatur, lalu menunggu dalam perulangan recv hingga nol byte dikembalikan melalui koneksi. Ini menjamin bahwa semua data diterima oleh serekan dan juga mengonfirmasi dengan serekan bahwa ia telah menerima semua data yang dikirimkan, serta menghindari masalah penggunaan kembali port yang disebutkan di atas.

Opsi soket SO_LINGER dapat diatur pada soket untuk mencegah port beralih ke status tunggu "aktif"; namun, ini tidak disarankan karena dapat menyebabkan efek yang tidak diinginkan, seperti mengatur ulang koneksi. Misalnya, jika data diterima oleh serekan tetapi tetap tidak diakui olehnya, dan komputer lokal menutup soket dengan SO_LINGER diatur di atasnya, koneksi antara kedua komputer diatur ulang dan data yang tidak diakui dibuang oleh serekan. Memilih waktu yang sesuai untuk berlama-lama sulit karena nilai batas waktu yang lebih kecil sering mengakibatkan koneksi yang tiba-tiba dibatalkan, sedangkan nilai batas waktu yang lebih besar membuat sistem rentan terhadap serangan penolakan layanan (dengan membuat banyak koneksi dan berpotensi mengulur-ulur/memblokir utas aplikasi). Menutup soket yang memiliki nilai batas waktu nonzero linger juga dapat menyebabkan panggilan closesocket diblokir.

Keamanan Soket yang Ditingkatkan

Keamanan soket yang ditingkatkan ditambahkan dengan rilis Windows Server 2003. Dalam rilis sistem operasi server Microsoft sebelumnya, keamanan soket default dengan mudah memungkinkan proses untuk membajak port dari aplikasi yang tidak curiga. Di Windows Server 2003, soket tidak dalam keadaan dapat dibagikan secara default. Oleh karena itu, jika aplikasi ingin mengizinkan proses lain untuk menggunakan kembali port tempat soket sudah terikat, aplikasi harus mengaktifkannya secara khusus. Jika demikian, soket pertama yang memanggil ikatan pada port harus memiliki SO_REUSEADDR diatur pada soket. Satu-satunya pengecualian untuk kasus ini terjadi ketika panggilan ikatan kedua dilakukan oleh akun pengguna yang sama yang melakukan panggilan asli untuk mengikat. Pengecualian ini hanya ada untuk memberikan kompatibilitas mundur.

Tabel di bawah ini menjelaskan perilaku yang terjadi di Windows Server 2003 dan sistem operasi yang lebih baru ketika soket kedua mencoba mengikat ke alamat yang sebelumnya terikat oleh soket pertama menggunakan opsi soket tertentu.

Catatan

Dalam tabel di bawah ini, "kartubebas" menunjukkan alamat wildcard untuk protokol yang diberikan (seperti "0.0.0.0" untuk IPv4 dan "::" untuk IPv6). "Spesifik" menunjukkan alamat IP tertentu yang ditetapkan antarmuka. Sel tabel menunjukkan apakah ikatan berhasil atau tidak ("Berhasil") atau kesalahan yang dikembalikan ("INUSE" untuk kesalahan WSAEADDRINUSE ; "ACCESS" untuk kesalahan WSAEACCES ).

Perhatikan juga bahwa dalam tabel khusus ini, kedua panggilan ikatan dilakukan di bawah akun pengguna yang sama.

Panggilan ikatan pertama Panggilan ikatan kedua
Default SO_REUSEADDR SO_EXCLUSIVEADDRUSE
Karakter kartubebas Spesifik Karakter kartubebas Spesifik Karakter kartubebas Spesifik
Default Karakter kartubebas INUSE Berhasil ACCESS Berhasil INUSE Berhasil
Spesifik Berhasil INUSE Berhasil ACCESS INUSE INUSE
SO_REUSEADDR Karakter kartubebas INUSE Berhasil Berhasil Berhasil INUSE Berhasil
Spesifik Berhasil INUSE Berhasil Berhasil INUSE INUSE
SO_EXCLUSIVEADDRUSE Karakter kartubebas INUSE ACCESS ACCESS ACCESS INUSE ACCESS
Spesifik Berhasil INUSE Berhasil ACCESS INUSE INUSE

Beberapa entri dalam tabel di atas merit penjelasan.

Misalnya, jika penelepon pertama mengatur SO_EXCLUSIVEADDRUSE pada alamat tertentu, dan pemanggil kedua mencoba memanggil ikatan dengan alamat kartubebas pada port yang sama, panggilan ikat kedua akan berhasil. Dalam kasus khusus ini, pemanggil kedua terikat ke semua antarmuka kecuali alamat khusus yang terikat dengan pemanggil pertama. Perhatikan bahwa kebalikan kasus ini tidak benar: jika penelepon pertama mengatur SO_EXCLUSIVEADDRUSE dan panggilan yang diikat dengan bendera wildcard, pemanggil kedua tidak dapat memanggil ikatan dengan port yang sama.

Perilaku pengikatan soket berubah ketika panggilan ikatan soket dilakukan di bawah akun pengguna yang berbeda. Tabel di bawah ini menentukan perilaku yang terjadi di Windows Server 2003 dan sistem operasi yang lebih baru ketika soket kedua mencoba mengikat ke alamat yang sebelumnya diikat oleh soket pertama menggunakan opsi soket tertentu dan akun pengguna yang berbeda.

Panggilan ikatan pertama Panggilan ikat kedua
Default SO_REUSEADDR SO_EXCLUSIVEADDRUSE
Karakter kartubebas Spesifik Karakter kartubebas Spesifik Karakter kartubebas Spesifik
Default Karakter kartubebas INUSE ACCESS ACCESS ACCESS INUSE ACCESS
Spesifik Berhasil INUSE Berhasil ACCESS INUSE INUSE
SO_REUSEADDR Karakter kartubebas INUSE ACCESS Berhasil Berhasil INUSE ACCESS
Spesifik Berhasil INUSE Berhasil Berhasil INUSE INUSE
SO_EXCLUSIVEADDRUSE Karakter kartubebas INUSE ACCESS ACCESS ACCESS INUSE ACCESS
Spesifik Berhasil INUSE Berhasil ACCESS INUSE INUSE

Perhatikan bahwa perilaku default berbeda saat panggilan ikatan dilakukan di bawah akun pengguna yang berbeda. Jika penelepon pertama tidak mengatur opsi apa pun pada soket dan mengikat ke alamat wildcard, pemanggil kedua tidak dapat mengatur opsi SO_REUSEADDR dan berhasil mengikat ke port yang sama. Perilaku default tanpa set opsi juga mengembalikan kesalahan.

Pada Windows Vista dan yang lebih baru, soket tumpukan ganda dapat dibuat yang beroperasi melalui IPv6 dan IPv4. Ketika soket tumpukan ganda terikat ke alamat wildcard, port yang diberikan dicadangkan pada tumpukan jaringan IPv4 dan IPv6 dan pemeriksaan yang terkait dengan SO_REUSEADDR dan SO_EXCLUSIVEADDRUSE (jika diatur) dibuat. Pemeriksaan ini harus berhasil pada kedua tumpukan jaringan. Misalnya, jika soket TCP tumpukan ganda diatur SO_EXCLUSIVEADDRUSE dan kemudian mencoba mengikat ke port 5000, maka tidak ada soket TCP lain yang sebelumnya dapat terikat ke port 5000 (baik kartubebas atau spesifik). Dalam hal ini jika soket TCP IPv4 sebelumnya terikat ke alamat loopback pada port 5000, panggilan ikat untuk soket tumpukan ganda akan gagal dengan WSAEACCES.

Strategi Aplikasi

Saat mengembangkan aplikasi jaringan yang beroperasi di lapisan soket, penting untuk mempertimbangkan jenis keamanan soket yang diperlukan. Aplikasi klien — aplikasi yang menghubungkan atau mengirim data ke layanan — jarang memerlukan langkah tambahan karena mereka mengikat port lokal acak (sementara). Jika klien memang memerlukan pengikatan port lokal tertentu agar berfungsi dengan benar, maka Anda harus mempertimbangkan keamanan soket.

Opsi SO_REUSEADDR memiliki sangat sedikit kegunaan dalam aplikasi normal selain dari soket multicast tempat data dikirimkan ke semua soket yang terikat pada port yang sama. Jika tidak, aplikasi apa pun yang mengatur opsi soket ini harus dirancang ulang untuk menghapus dependensi karena sangat rentan terhadap "pembajakan soket". Selama opsi soket SO_REUSEADDR dapat digunakan untuk berpotensi membajak port dalam aplikasi server, aplikasi harus dianggap tidak aman.

Semua aplikasi server harus mengatur SO_EXCLUSIVEADDRUSE untuk tingkat keamanan soket yang kuat. Tidak hanya mencegah perangkat lunak berbahaya membajak port, tetapi juga menunjukkan apakah aplikasi lain terikat ke port yang diminta atau tidak. Misalnya, panggilan untuk mengikat alamat kartubebas oleh proses dengan set opsi soket SO_EXCLUSIVEADDRUSE akan gagal jika proses lain saat ini terikat ke port yang sama pada antarmuka tertentu.

Terakhir, meskipun keamanan soket telah ditingkatkan di Windows Server 2003, aplikasi harus selalu mengatur opsi soket SO_EXCLUSIVEADDRUSE untuk memastikan bahwa ia mengikat ke semua antarmuka tertentu yang telah diminta proses. Keamanan soket di Windows Server 2003 menambahkan peningkatan tingkat keamanan untuk aplikasi warisan, tetapi pengembang aplikasi harus tetap merancang produk mereka dengan mempertimbangkan semua aspek keamanan.