章節概覽#
本章探討位於 application layer 的網路應用程式,包括用戶端(client)與伺服器端(server)。這一層位於網路堆疊的最頂層,最貼近終端使用者。章節涵蓋了基本的網路服務運作原理、常見伺服器(特別是 SSH)、診斷工具、網路安全概念,以及 socket 程式設計基礎。
網路用戶端透過作業系統的 transport layer 協定(TCP 和 UDP)連接到對應的伺服器。伺服器程式可以直接監聽 port,也可以透過次級伺服器來運作。
10.1 服務的基礎#
TCP 服務建立在簡單、不間斷的雙向資料串流之上。最直接的方式是用 telnet 連接到未加密的 web server:
$ telnet example.org 80連線成功後,輸入 HTTP 請求:
GET / HTTP/1.1
Host: example.org按兩次 ENTER 後,伺服器會回傳 HTML 內容。這個練習示範了:
- 遠端主機有一個 web server process 正在監聽 TCP port 80
telnet是發起連線的用戶端
telnet原本是設計用來遠端登入的,但 telnet 遠端登入伺服器完全不安全。不過telnet用戶端對於除錯遠端 TCP 服務仍然很有用。它無法用於 UDP 或 TCP 以外的 transport layer。若需要通用網路用戶端,可考慮使用netcat。
10.2 深入觀察#
使用 curl 這個了解 HTTP application layer 協定的命令列工具,可以記錄通訊細節:
$ curl --trace-ascii trace_file http://www.example.org/從 trace 檔案可以觀察到:
- curl 先在 transport layer 建立 TCP 連線
- 然後在 application layer 發送 HTTP 請求(header)
- 伺服器先回傳 response header,再回傳實際文件內容
- header 與 data 之間以空白行分隔
作業系統在處理封包時並不區分 header 和 data,這些區別完全在 user-space 的應用程式內部處理。對 OS 來說,這些都只是資料串流。
10.3 網路伺服器#
大多數網路伺服器的運作方式類似其他 daemon,差別在於它們與 network port 互動。常見的網路伺服器包括:
- httpd, apache, apache2, nginx — Web 伺服器
- sshd — Secure Shell daemon
- postfix, qmail, sendmail — 郵件伺服器
- cupsd — 列印伺服器
- nfsd, mountd — 網路檔案系統 daemon
- smbd, nmbd — Windows 檔案分享 daemon
- rpcbind — RPC portmap 服務 daemon
伺服器通常以多行程方式運作:監聽行程收到新連線時,使用 fork() 建立 worker 子行程來處理該連線。高效能伺服器(如 Apache)可能在啟動時預先建立多個 worker process。
10.3.1 Secure Shell#
SSH 是遠端存取 Unix 機器的事實標準,取代了不安全的 telnet 和 rlogin。SSH 使用 public-key cryptography 進行身份驗證,並加密所有 session 資料。
SSH 的主要功能:
- 加密密碼和所有 session 資料
- Tunnel 其他網路連線(包括 X Window System)
- 支援幾乎所有作業系統的用戶端
- 使用 key 進行主機驗證
OpenSSH 是最常見的實作,用戶端程式為 ssh,伺服器端為 sshd。目前只支援 SSH protocol version 2。
Public-key cryptography:與對稱加密不同,public key 只能加密訊息但無法解密,只有對應的 private key 才能解密。這使得金鑰管理更容易,因為 private key 不需要傳輸。
10.3.2 sshd 伺服器#
sshd 伺服器的設定檔位於 /etc/ssh/ 目錄,伺服器設定檔為 sshd_config(注意不要與用戶端的 ssh_config 混淆)。
重要的設定參數:
- HostKey — 指定 host key 檔案
- PermitRootLogin — 是否允許 root 透過 SSH 登入
- LogLevel — syslog 記錄層級(預設 INFO)
- X11Forwarding — 是否啟用 X Window System tunneling
建立 Host Keys:OpenSSH 使用 RSA 和 DSA 公鑰演算法,每組金鑰包含公鑰(.pub)和私鑰。
# ssh-keygen -t rsa -N '' -f /etc/ssh/ssh_host_rsa_key
# ssh-keygen -t dsa -N '' -f /etc/ssh/ssh_host_dsa_key絕對不要讓任何人看到 private key,即使是在你自己的系統上。如果有人取得了 private key,你的系統就有被入侵的風險。
啟動 SSH 伺服器:
# systemctl enable sshd
# systemctl start sshd10.3.3 fail2ban#
在網際網路上開放 SSH 伺服器會不斷收到暴力破解攻擊。fail2ban 透過監控 log 訊息,在偵測到某主機在一定時間內多次登入失敗後,使用 iptables 建立規則封鎖該主機的流量。
10.3.4 SSH 用戶端#
登入遠端主機:
$ ssh remote_username@remote_host透過 SSH 傳輸資料(pipe):
$ tar zcvf - dir | ssh remote_host tar zxvf -用戶端設定檔為 /etc/ssh/ssh_config。最常見的問題是 known_hosts 中的 public key 與遠端主機不匹配,通常是因為遠端主機更換了金鑰。
SSH 檔案傳輸工具:
- scp — 類似
cp的安全複製工具 - sftp — 類似 FTP 的安全檔案傳輸工具
$ scp user@host:file .
$ scp file user@host:dir如果需要比
scp和sftp更多功能(例如頻繁傳輸大量檔案),可以考慮使用rsync。
10.4 systemd 之前的網路連線伺服器:inetd/xinetd#
在 systemd 和 socket unit 普及之前,inetd 是一種 superserver,負責標準化伺服器程式與 network port 之間的介面。inetd 讀取設定檔並監聽定義的 port,當新連線進入時,將其附加到新啟動的 process。
xinetd 是 inetd 的改良版本,提供更好的存取控制,但已幾乎完全被 systemd 取代。
在
iptables等較低階防火牆流行之前,許多管理員使用 TCP wrapper(tcpd、/etc/hosts.allow、/etc/hosts.deny)來控制網路服務存取。這套系統現在已經大致淘汰。
10.5 診斷工具#
10.5.1 lsof#
lsof 不僅可以追蹤開啟的檔案,也能列出正在使用或監聽 port 的程式:
# lsof -i依協定和 port 過濾:
# lsof -iTCP:443依連線狀態過濾,例如只顯示監聽中的 TCP process:
# lsof -iTCP -sTCP:LISTEN- 使用
-n停用名稱解析以加速輸出 - 使用
-P停用/etc/services的 port 名稱查詢
10.5.2 tcpdump#
tcpdump 將網路介面設為 promiscuous mode,報告每個通過的封包:
# tcpdump使用 filter 過濾封包:
# tcpdump tcp
# tcpdump udp or port 80 or port 443常用的 primitives:
tcp/udp— TCP 或 UDP 封包ip/ip6— IPv4 或 IPv6 封包port port— 指定 port 的 TCP/UDP 封包host host— 來自或送往指定主機的封包net network— 來自或送往指定網路的封包
可使用 and、or、! 等 operator 組合條件。
使用
tcpdump時要注意:雖然現在大部分重要的網路流量都透過 TLS 加密,但你不應該在未經授權的情況下嗅探他人網路。
10.5.3 netcat#
netcat(或 nc)是一個比 telnet 更靈活的通用網路工具,可以:
- 連接遠端 TCP/UDP port
- 指定本地 port 並監聽
- 掃描 port
- 重新導向標準 I/O 到網路連線
$ netcat host port
$ netcat -l port_number- 使用
-u選項指定 UDP 而非 TCP - 使用
-4或-6強制指定 IPv4 或 IPv6
10.5.4 Port Scanning#
Nmap(Network Mapper)掃描機器上所有 port 以尋找開放的服務:
$ nmap 10.1.2.2如果你要掃描的網路由他人管理,請先取得許可。網路管理員會監控 port scan 行為,且通常會限制掃描機器的存取。
建議從至少兩個位置進行掃描:本機和本地網路外部的機器,以了解防火牆的封鎖情況。Nmap 也支援以 -6 選項掃描 IPv6 port。
10.6 Remote Procedure Calls#
RPC(Remote Procedure Call)是 application layer 底層的系統,讓程式可以呼叫在遠端伺服器上執行的函式。每種遠端伺服器程式由一個 program number 識別。
RPC 使用 TCP 和 UDP 等 transport protocol,並需要 rpcbind 服務來將 program number 對應到 TCP/UDP port。
$ rpcinfo -p localhostNFS(Network File System)和 NIS(Network Information Service)都使用 RPC。雖然在獨立機器上不必要,但 RPC 持續存在,例如 GNOME 的 File Access Monitor (FAM) 就需要 rpcbind。
10.7 網路安全#
Linux 作為流行的伺服器平台,容易成為攻擊目標。基本的安全守則:
- 盡量減少執行的服務 — 不使用的服務就不要開啟
- 盡量使用防火牆封鎖 — 內部服務(如 RPC port 111)不應暴露在外
- 追蹤對外提供的服務 — 保持軟體更新,取得安全警報
- 使用 LTS(長期支援)發行版 — 安全團隊主要關注穩定版本
- 不給不需要的人帳號 — 本機存取比遠端入侵更容易提權
- 避免安裝來路不明的套件 — 可能包含 Trojan horse
三種基本的網路攻擊類型:
- Full compromise — 取得 superuser 存取權限(完全控制)
- Denial-of-service (DoS) attack — 癱瘓網路服務或使電腦故障
- Malware — 惡意軟體(Linux 使用者較少受影響,但 Linux malware 確實存在)
10.7.1 常見漏洞#
- Direct attack — 直接攻擊未受保護的服務,例如 buffer overflow exploit(已被 ASLR 等技術部分緩解)
- Cleartext password sniffing attack — 擷取以明文傳輸的密碼
應該停用的不安全服務:
- ftpd — FTP 伺服器漏洞多,且使用明文密碼
- telnetd, rlogind, rexecd — 所有遠端 session 資料以明文傳輸
若需要為不支援加密的服務提供加密,可以使用 Stunnel 作為加密 wrapper。
10.7.2 安全資源#
- SANS Institute — 安全訓練、漏洞週報
- CERT Division(Carnegie Mellon University)— 最嚴重問題的資訊
- Insecure.org — Nmap 和各種網路漏洞測試工具
如果對網路安全有興趣,應學習 TLS(Transport Layer Security)及其前身 SSL(Secure Socket Layer),它們透過 public-key encryption 和 certificate 來保護網路交易。
10.8 展望#
如果想實際操作較複雜的網路伺服器,常見的選擇有 Apache、nginx web server 和 Postfix 郵件伺服器。如果機器位於防火牆或 NAT router 後方,可以安心實驗各種設定。
本章從 kernel space 逐漸轉向 user space,後續章節將更深入介紹 socket 如何橋接 kernel 的 transport layer 和 user-space application layer。
10.9 Network Sockets#
Socket 是 process 透過 kernel 存取網路的介面,也是 user space 與 kernel space 之間的邊界,常用於 interprocess communication (IPC)。
不同的 socket 類型對應不同的網路存取方式:
- SOCK_STREAM — TCP 連線(stream socket)
- SOCK_DGRAM — UDP 連線(datagram socket)

Figure 10-1: One method for accepting and processing incoming connections
伺服器處理連入連線的典型流程:
- Master process 使用 listener socket 監聽網路連線
- 偵測到新連線後,呼叫
accept()建立專用的 read/write socket - 使用
fork()建立子行程處理該連線 - 原始的 listener socket 繼續監聽新連線
Socket 的彈性在於:如果需要更改底層 transport layer,只需修改初始化程式碼,收發資料的部分大致不需變動。
10.10 Unix Domain Sockets#
不是所有使用網路機制的應用程式都需要連接兩台不同的主機。Unix domain socket 是一種特殊的 socket,用於同一台機器上 process 之間的通訊(IPC),例如 systemd 和 NetworkManager 透過 D-Bus 溝通。
Unix domain socket 的特點:
- 不是真正的 network socket,背後沒有網路,甚至不需要設定網路
- 行為類似 network socket:可以監聽、接受連線,選擇類似 TCP 或 UDP 的行為
- 不一定需要綁定到 socket 檔案,也可以建立 unnamed socket
- 效能更好,因為 kernel 不需要經過完整的網路子系統
開發者偏好 Unix domain socket 的兩個原因:
- 可利用檔案系統權限控制存取
- 無網路互動,更簡單且較不容易受到網路入侵
例如 D-Bus 的 socket 檔案位於 /var/run/dbus/,MySQL 的 Unix domain socket 位於 /var/run/mysqld/mysqld.sock。
查看系統上的 Unix domain socket:
# lsof -U