Jaringan Dasar untuk Sysadmin

Jaringan Dasar untuk Sysadmin

Bitnesia • Aug 31, 2026 59 •EN

Bab 19.3.3 menutup pembahasan ping dengan janji bahwa tool jaringan lain seperti curl dan ss "dibahas jauh lebih dalam di Bab 22", dan Bab 21.4.1 juga menunda pembahasan health check jaringan yang lebih menyeluruh ke bab ini. Sekarang saatnya menepati kedua janji itu. Sysadmin menghabiskan sebagian besar waktu troubleshooting untuk satu pertanyaan sederhana: server ini bisa dihubungi atau tidak, dan kalau tidak, di lapisan mana masalahnya berhenti? Apakah host-nya sama sekali tidak merespons, port aplikasinya tertutup, atau service-nya aktif tapi merespons dengan error? Bab ini membangun kemampuan menjawab pertanyaan itu secara terstruktur, dimulai dari perintah jaringan dasar (22.1), lanjut ke health check otomatis yang menggabungkan beberapa lapis pengecekan sekaligus (22.2), uji koneksi API yang memvalidasi bukan cuma status HTTP tapi juga isi response-nya (22.3), dan ditutup studi kasus script yang mengecek konektivitas banyak server sekaligus (22.4). Bab 23 nanti melanjutkan sebagian tool di sini (khususnya ss) dari sudut pandang berbeda, yaitu audit keamanan port terbuka, jadi fokus bab ini murni pada diagnosis dan monitoring konektivitas, bukan hardening.

22.1 Perintah Jaringan Dasar

Empat sub-bab ini membedah tool jaringan yang paling sering dipakai Sysadmin sehari-hari, plus detail yang sering luput diperhatikan sampai akhirnya jadi sumber bug yang membingungkan.

22.1.1 Uji Endpoint HTTP dengan curl

Bab 20.2.4 sudah memakai curl -s -o /dev/null -w '%{http_code}' untuk mengecek endpoint webhook, dan Bab 21.4.2 memakai curl -sf untuk health check deployment. Sub-bab ini membedah opsi-opsi curl itu lebih lengkap, karena keduanya baru memakai sebagian kecil dari kemampuan curl untuk diagnosis jaringan.

curl -I https://api.example.com/status

Opsi -I/--head mengirim request HEAD alih-alih GET, sesuai dokumentasi resmi curl, sehingga cuma header response yang diambil tanpa body sama sekali, cocok untuk cek cepat apakah endpoint hidup tanpa mengunduh seluruh isinya. Catatan dari pengalaman lapangan: sebagian web server atau reverse proxy yang dikonfigurasi ketat kadang menolak method HEAD meski method GET ke endpoint yang sama berjalan normal, jadi kalau -I memberi hasil aneh (misalnya 405 Method Not Allowed) padahal endpoint-nya sendiri sehat, jangan buru-buru simpulkan endpoint bermasalah, coba dulu dengan -s -o /dev/null -w '%{http_code}\n' yang memakai GET biasa.

curl -sS -L --connect-timeout 5 --max-time 15 -o /dev/null -w '%{http_code}\n' https://api.example.com/status

-L/--location membuat curl otomatis mengikuti redirect HTTP (kode 3xx), penting karena tanpa opsi ini, endpoint yang mengalihkan misalnya dari http:// ke https:// akan terekam sebagai kode 301/302 alih-alih kode status endpoint tujuan sebenarnya. --connect-timeout membatasi waktu maksimal khusus fase pembukaan koneksi TCP, sementara --max-time membatasi keseluruhan durasi request dari awal sampai selesai, sesuai dokumentasi resmi curl; keduanya beda lapisan dan sebaiknya dipakai berbarengan, karena --connect-timeout saja tidak menolong kalau koneksi berhasil terbuka tapi server menggantung lama sebelum mengirim response.

22.1.2 wget sebagai Alternatif curl

curl dan wget sering dianggap saling menggantikan, padahal keduanya punya penekanan berbeda: curl dirancang sebagai client transfer data serbaguna yang hasilnya gampang diolah lebih lanjut di script (lewat stdout atau opsi -w), sedangkan wget punya kekuatan khusus di urusan mengunduh, termasuk mengunduh rekursif seluruh isi sebuah website dan melanjutkan unduhan yang terputus.

wget --spider -q https://api.example.com/status; echo "Exit status: $?"

Opsi --spider membuat wget berperilaku seperti web spider, cuma memeriksa keberadaan halaman tanpa benar-benar mengunduh isinya, sesuai dokumentasi resmi GNU Wget. Kombinasi dengan -q (quiet, meredam output) membuat pola ini praktis dipakai di script murni untuk mengecek exit status-nya saja, mirip kegunaan curl -sf di 21.4.2. Untuk kebutuhan resume unduhan file besar yang terputus di tengah jalan, misalnya menarik arsip backup besar dari server lain, opsi -c/--continue melanjutkan dari byte terakhir yang sudah diterima alih-alih mengunduh ulang dari awal; ini salah satu keunggulan wget yang tidak dimiliki curl semudah itu. Untuk kebutuhan health check endpoint API sehari-hari seperti sisa bab ini, curl tetap jadi pilihan utama karena output-nya jauh lebih mudah diproses lewat opsi -w dan lebih lazim tersedia secara bawaan di berbagai image container minimal.

22.1.3 Melihat Koneksi Aktif dengan ss

netstat dulu jadi tool standar untuk melihat koneksi jaringan aktif dan port yang sedang listening, tapi banyak distro modern sudah men-deprecate paket net-tools tempat netstat berasal, digantikan ss dari paket iproute2. Dokumentasi resmi Red Hat untuk RHEL 7 secara eksplisit menyebutkan paket net-tools di-deprecate dan digantikan tool iproute2, pola yang sama diikuti sebagian besar distro turunan Debian dan Arch di era yang berdekatan; hasilnya, ss kini terpasang secara bawaan di kebanyakan distro Linux modern, sementara netstat kadang perlu dipasang manual lewat paket net-tools terpisah. ss membaca data koneksi langsung dari kernel lewat netlink socket, sementara netstat mem-parsing file teks /proc/net/tcp, membuat ss jauh lebih cepat terutama di server dengan jumlah koneksi sangat banyak.

ss -tuln

Empat opsi ini sesuai man ss: -t menampilkan socket TCP, -u menampilkan socket UDP, -l menampilkan cuma socket yang sedang listening (secara default socket listening ini justru disembunyikan), dan -n menampilkan nilai numerik apa adanya (port dan alamat) tanpa mencoba me-resolve-nya jadi nama service yang lebih mudah dibaca tapi butuh waktu tambahan untuk lookup. Kombinasi ini jadi cara tercepat menjawab pertanyaan "service apa saja yang sedang membuka port di server ini", pertanyaan awal yang sama persis dibutuhkan sebelum audit keamanan port terbuka di Bab 23.3, walau tujuan pemakaiannya di bab ini murni diagnosis konektivitas, bukan hardening.

sudo ss -tnp state established '( dport = :443 or dport = :80 )'

Opsi -p menambahkan informasi proses (nama dan PID) pemilik tiap socket, sesuai man ss, tapi informasi ini cuma muncul lengkap kalau dijalankan dengan hak akses root karena melibatkan pembacaan detail proses milik user lain; menjalankan tanpa sudo biasanya cuma menampilkan socket milik user yang sedang login. Filter state established mempersempit tampilan ke koneksi yang sudah benar-benar terbentuk (bukan sekadar listening), dan ekspresi dalam kurung memfilter berdasarkan port tujuan, berguna waktu perlu memastikan koneksi keluar ke API pihak ketiga di port 443 benar-benar sedang aktif, bukan cuma dicoba lalu gantung.

22.1.4 Diagnosis Konektivitas dengan ping

Pola dasar ping -c 1 -W 2 host sudah diperkenalkan di Bab 19.3.3 sebagai komponen dashboard status server. Sub-bab ini melengkapi detail yang belum dibahas di sana: cara membaca exit status dan batasannya sebagai indikator "hidup atau matinya" sebuah host.

ping -c 3 -W 2 10.0.0.5
echo "Exit status: $?"

Menurut dokumentasi resmi ping (paket iputils yang lazim dipakai distro Linux modern), exit status 0 berarti paket berhasil diterima kembali, 1 berarti tidak ada balasan sama sekali (atau jumlah balasan lebih sedikit dari -c yang diminta sebelum batas waktu habis), dan 2 berarti ada error lain selama eksekusi (misalnya nama host tidak bisa di-resolve). Dokumentasinya sendiri menegaskan tujuan desain ini: exit status dirancang eksplisit supaya bisa langsung dipakai script untuk mengecek hidup-tidaknya sebuah host tanpa perlu mem-parsing output teksnya.

Yang perlu jujur diungkap dari pengalaman lapangan: ping gagal bukan berarti otomatis service di host itu mati. ping memakai protokol ICMP, dan banyak firewall (termasuk konfigurasi cloud provider seperti security group) sengaja memblokir ICMP masuk sebagai kebiasaan hardening standar, sementara port aplikasi yang sebenarnya (misalnya 443 untuk HTTPS) tetap terbuka dan berfungsi normal. Sebaliknya, ping berhasil juga bukan jaminan aplikasi di host itu sehat, cuma membuktikan host-nya merespons di lapisan jaringan paling dasar. Karena itu, ping paling tepat dipakai sebagai pemeriksaan awal tercepat (host-nya menyala atau tidak), bukan satu-satunya sinyal kesehatan sebuah service; 22.2 membangun pengecekan berlapis yang tidak berhenti cuma di ping.

ToolYang DiperiksaBatasan Utama
pingHost merespons di lapisan jaringan (ICMP)Sering diblokir firewall meski service sebenarnya sehat
ssPort lokal sedang listening/koneksi aktifCuma berlaku untuk mesin lokal, tidak bisa cek host lain lewat jaringan
curl/wgetEndpoint HTTP(S) merespons dengan status tertentuCuma untuk protokol yang didukung (HTTP, FTP, SMTP, dll.), tidak generik untuk semua TCP

22.2 Health Check Endpoint Otomatis

Tabel penutup 22.1 menunjukkan tiap tool cuma menjawab sebagian pertanyaan. Dua sub-bab ini menyusun health check yang mengecek beberapa lapis sekaligus: apakah port-nya terbuka, lalu apakah aplikasi di baliknya benar-benar merespons dengan sehat.

22.2.1 Cek Port TCP Tanpa Tool Tambahan

Bash sendiri, tanpa nc (netcat) atau tool eksternal lain, sebenarnya sudah bisa membuka koneksi TCP mentah lewat fitur redirection khusus /dev/tcp/host/port. Menurut GNU Bash Reference Manual, kalau host adalah hostname atau alamat IP yang valid dan port adalah nomor port yang valid, Bash akan mencoba membuka socket TCP yang sesuai. Fitur ini murni bawaan Bash (bukan file device sungguhan di kebanyakan sistem), jadi tidak berlaku di shell lain seperti sh POSIX murni atau dash.

Satu syarat penting yang jarang disadari: dukungan /dev/tcp bergantung pada opsi waktu kompilasi --enable-net-redirections saat Bash itu sendiri dibangun. Opsi ini aktif di kebanyakan build Bash modern, tapi beberapa distro (Debian dan turunannya pernah dikenal mengompilasi Bash tanpa fitur ini di rilis-rilis lama) bisa saja mematikannya, dengan gejala error No such file or directory tepat di baris yang mencoba membuka /dev/tcp. Karena statusnya bisa berbeda-beda antar sistem dan cenderung berubah dari waktu ke waktu, jangan berasumsi fitur ini pasti tersedia di server produksi; uji dulu satu baris sederhana seperti timeout 2 bash -c 'echo > /dev/tcp/example.com/80' && echo tersedia sebelum mengandalkannya di script yang berjalan otomatis, dan siapkan nc -z host port sebagai alternatif kalau netcat memang sudah terpasang di server itu.

cek_port() {
    local host="$1" port="$2" timeout="${3:-3}"
    if timeout "$timeout" bash -c "echo > /dev/tcp/$host/$port" 2>/dev/null; then
        echo "Port $port di $host terbuka"
        return 0
    else
        echo "Port $port di $host tertutup atau tidak merespons"
        return 1
    fi
}

cek_port api.example.com 443

echo > /dev/tcp/$host/$port mencoba membuka koneksi lalu langsung menutupnya lagi setelah echo selesai, cukup untuk sekadar menguji port-nya bisa "disambungi" atau tidak tanpa perlu benar-benar mengirim/menerima data aplikasi. Perintah timeout di depannya penting karena percobaan koneksi ke port yang tertutup rapat oleh firewall (bukan sekadar tidak ada service yang listen) bisa menggantung lama menunggu connection timeout bawaan sistem yang defaultnya sering puluhan detik atau bahkan lebih; membungkusnya dengan timeout memberi batas waktu eksplisit yang bisa dikontrol script. Teknik ini pas dipakai untuk cek cepat "apakah port service database/API ini terbuka dari server ini", tanpa perlu memasang nc di setiap server yang mungkin belum tentu tersedia.

22.2.2 Fungsi Health Check HTTP Generik

Pola curl -sf -o /dev/null dari 21.4.2 dan HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' ...) dari 20.2.4 bisa digabung jadi satu fungsi generik yang menerima URL apa pun, dilengkapi timeout dan retry sesuai pola --retry yang sudah dibahas di 20.2.4.

cek_endpoint() {
    local url="$1" timeout="${2:-10}"
    local kode
    kode=$(curl -s -o /dev/null -w '%{http_code}' \
        --connect-timeout 5 --max-time "$timeout" --retry 2 --retry-delay 2 \
        "$url")
    if [[ "$kode" =~ ^2 ]]; then
        echo "OK ($kode)"
        return 0
    else
        echo "GAGAL ($kode)"
        return 1
    fi
}

cek_endpoint "https://api.example.com/health"

Pengecekan [[ "$kode" =~ ^2 ]] menganggap sehat kalau kode statusnya diawali angka 2 (rentang 2xx, sukses), lebih longgar dibanding cuma mencocokkan 200 persis, karena sebagian endpoint kadang sengaja membalas 201 atau 204 untuk kondisi normal tertentu. Kalau curl sama sekali gagal terhubung (host tidak bisa dijangkau, DNS gagal di-resolve, timeout habis), variabel kode berisi string kosong, bukan angka, sehingga tetap jatuh ke cabang else dengan aman karena regex ^2 juga tidak cocok dengan string kosong.

22.3 Uji Koneksi API Sederhana dari Script

Health check di 22.2 baru memastikan endpoint merespons dengan kode status yang benar. Untuk API sungguhan, itu belum cukup: endpoint bisa saja membalas 200 OK tapi isi response-nya justru menunjukkan error di level aplikasi (pola umum di banyak REST API), atau butuh autentikasi lebih dulu sebelum bisa diuji dengan jujur.

22.3.1 Request API dengan Header Autentikasi

curl -s -o /dev/null -w '%{http_code}\n' \
    -H "Authorization: Bearer $API_TOKEN" \
    -H "Accept: application/json" \
    "https://api.example.com/v1/ping"

Opsi -H menambahkan header HTTP kustom, dipakai berulang untuk tiap header berbeda seperti contoh di atas. $API_TOKEN di sini sebaiknya tidak pernah ditulis langsung sebagai literal di dalam script (apalagi kalau script itu ikut ter-commit ke Git), melainkan dibaca dari environment variable atau file terpisah yang permission-nya dibatasi, pola yang sama seperti source /etc/deploy-pipeline/alert-notifikasi.env di 21.4.2 untuk token Telegram. Bab 23.1 membahas lebih dalam risiko keamanan seputar credential yang bocor lewat script maupun riwayat command shell.

22.3.2 Validasi Response Body dengan jq

Sub-bab 20.2.3 sudah memperkenalkan jq untuk membangun payload JSON dengan aman. Kali ini jq dipakai ke arah sebaliknya, membaca dan memvalidasi isi response JSON dari API.

cek_api_status() {
    local url="$1"
    local response status_field

    response=$(curl -s --max-time 10 "$url")
    status_field=$(echo "$response" | jq -r '.status // "unknown"' 2>/dev/null)

    if [[ "$status_field" == "ok" ]]; then
        echo "API sehat: status=$status_field"
        return 0
    else
        echo "API bermasalah: status=$status_field"
        return 1
    fi
}

cek_api_status "https://api.example.com/v1/health"

Operator // pada jq menyediakan nilai fallback ("unknown") kalau field .status tidak ada atau bernilai null di response, mencegah variabel status_field jadi kosong begitu saja yang bisa membingungkan saat dibaca dari log. 2>/dev/null di baris jq meredam pesan error kalau body response-nya ternyata bukan JSON valid sama sekali (misalnya API sedang down dan yang dibalas justru halaman error HTML dari load balancer di depannya), supaya script tidak berhenti gara-gara error parsing yang sebenarnya juga mengindikasikan API sedang bermasalah. Pendekatan ini melengkapi cek_endpoint() di 22.2.2: kode status HTTP 200 cuma bilang "server merespons", sementara validasi field status di body-nya bilang "aplikasinya sendiri mengaku sehat", dua hal yang tidak selalu sejalan.

22.4 Studi Kasus: Cek Konektivitas Multi-Server

Studi kasus penutup menggabungkan seluruh lapisan pengecekan bab ini, ping, port TCP, dan HTTP health check, jadi satu script yang mengecek banyak server sekaligus dan melaporkan di lapisan mana masing-masing bermasalah kalau ada yang gagal.

22.4.1 Rancangan Script

Script cek-konektivitas.sh membaca daftar server dari associative array (Bab 4.2), tiap server diperiksa berurutan lewat tiga lapis: (1) ping untuk memastikan host hidup di jaringan, (2) cek port TCP lewat fungsi cek_port() dari 22.2.1 untuk memastikan service-nya listen, (3) cek_endpoint() dari 22.2.2 untuk memastikan aplikasinya benar-benar merespons sehat. Kalau lapisan awal sudah gagal, lapisan berikutnya untuk server yang sama dilewati saja karena hasilnya sudah pasti gagal juga, menghemat waktu eksekusi dibanding tetap menjalankan ketiganya secara membabi buta.

22.4.2 Implementasi cek-konektivitas.sh

#!/bin/bash
set -uo pipefail

declare -A SERVERS=(
    [app-01]="10.0.0.11|443|https://10.0.0.11/health"
    [app-02]="10.0.0.12|443|https://10.0.0.12/health"
    [db-01]="10.0.0.21|5432|"
)

LOG_FILE="/var/log/cek-konektivitas.log"
GAGAL=0

log() {
    printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$LOG_FILE"
}

cek_port() {
    local host="$1" port="$2" timeout="${3:-3}"
    timeout "$timeout" bash -c "echo > /dev/tcp/$host/$port" 2>/dev/null
}

cek_endpoint() {
    local url="$1"
    local kode
    kode=$(curl -s -o /dev/null -w '%{http_code}' \
        --connect-timeout 5 --max-time 10 --retry 2 --retry-delay 2 "$url")
    [[ "$kode" =~ ^2 ]]
}

for nama in "${!SERVERS[@]}"; do
    IFS='|' read -r host port url <<< "${SERVERS[$nama]}"

    if ! ping -c 1 -W 2 "$host" &> /dev/null; then
        log "GAGAL $nama ($host): tidak merespons ping"
        GAGAL=$((GAGAL + 1))
        continue
    fi

    if ! cek_port "$host" "$port"; then
        log "GAGAL $nama ($host:$port): port tertutup"
        GAGAL=$((GAGAL + 1))
        continue
    fi

    if [[ -n "$url" ]]; then
        if ! cek_endpoint "$url"; then
            log "GAGAL $nama ($host): endpoint HTTP tidak sehat"
            GAGAL=$((GAGAL + 1))
            continue
        fi
    fi

    log "OK $nama ($host:$port)"
done

if (( GAGAL > 0 )); then
    log "Selesai, $GAGAL server bermasalah"
    exit 1
fi

log "Selesai, semua server sehat"

Format nilai SERVERS sengaja dipadatkan jadi satu string dipisah | (host, port, URL health check) karena Bash tidak mendukung array bersarang secara native; IFS='|' read -r host port url <<< "..." memecahnya kembali jadi tiga variabel terpisah, pola parsing yang sama prinsipnya dengan pemrosesan CSV di Bab 11.4. Entri db-01 sengaja mengosongkan bagian URL karena database biasanya tidak punya endpoint HTTP untuk dicek, cukup berhenti di lapisan cek port; blok if [[ -n "$url" ]] melewati lapisan ketiga kalau memang tidak relevan untuk server itu. set -uo pipefail dipakai tanpa -e, alasan yang sama seperti 21.4.2 dan 20.4.2: script ini harus tetap lanjut memeriksa server berikutnya sekalipun satu server di tengah daftar gagal, bukan langsung berhenti total.

22.4.3 Verifikasi dan Interpretasi Hasil

chmod +x cek-konektivitas.sh
./cek-konektivitas.sh
echo "Exit status: $?"

Perhatikan baris log tiap server untuk melihat di lapisan mana kegagalan terjadi, bukan cuma "gagal" tanpa detail. Kegagalan di lapisan ping mengarah ke masalah jaringan dasar atau host mati total; kegagalan di lapisan port mengarah ke service yang belum jalan atau firewall yang memblokir port spesifik itu; kegagalan di lapisan endpoint HTTP mengarah ke aplikasi yang jalan tapi bermasalah secara internal (database di baliknya down, misalnya). Untuk menguji jalur gagalnya secara sengaja, ubah salah satu nilai port di SERVERS jadi angka yang pasti tertutup (misalnya 9999) lalu jalankan ulang, pastikan log mencatat "port tertutup" persis untuk server itu dan exit status akhirnya 1. Untuk dipakai produksi, sambungkan variabel GAGAL di akhir script ke kirim_alert() dari 20.4.2 supaya Sysadmin langsung mendapat notifikasi begitu ada server bermasalah, dan jadwalkan lewat cron atau systemd timer (Bab 18) supaya berjalan otomatis tiap beberapa menit, bukan cuma dijalankan manual sesekali.

Bab ini melengkapi kemampuan Sysadmin mendiagnosis konektivitas secara berlapis, dari perintah jaringan paling dasar sampai health check API yang memvalidasi isi response-nya. Bab 23 melanjutkan ke topik keamanan, memakai kembali ss dari 22.1.3 tapi kali ini untuk mengaudit port mana saja yang seharusnya tidak terbuka ke publik, sekaligus membahas cara menghindari command injection dan credential bocor yang sempat disinggung sekilas di 22.3.1.