伺服器安全基礎:打開門之前,先檢查鎖吧

當它成為「我的伺服器」那一刻,一切都是我的責任

上次,我翻過了 Linux CLI 與權限(Permission)這道牆。chmod、chown,還有絕對不能做的 chmod 777。對單一檔案的存取控制,總算抓到了一點感覺。

但那時的我犯了一個天大的誤會。以為只要把「檔案權限」管好,伺服器就安全了。

「伺服器安全?那不是資安團隊的事嗎?」

如果是大企業,或許是這樣。但我是獨立開發者。伺服器管理員、資安負責人、網路工程師,全部都是「我自己」。所有的資安責任,都壓在我的肩膀上。

而讓我真正意識到這件事的,是某個星期一早上發現的伺服器連線紀錄。

檔案權限(chmod)只是房間裡抽屜的鎖而已。整棟建築的大門,必須另外管理。

危機:有人一直在敲我伺服器的大門

星期一早上,我像往常一樣用 SSH 連進伺服器查看日誌,結果發現了不對勁的東西。

# 檢查最近 SSH 登入失敗的紀錄
$ grep "Failed password" /var/log/auth.log | tail -20

看到畫面上跑出來的日誌,我當場起雞皮疙瘩。

Feb 10 03:14:22 sshd: Failed password for root from 185.220.xx.xx
Feb 10 03:14:25 sshd: Failed password for root from 185.220.xx.xx
Feb 10 03:14:27 sshd: Failed password for admin from 185.220.xx.xx
Feb 10 03:14:30 sshd: Failed password for ubuntu from 185.220.xx.xx
...

從凌晨三點開始,數百次的登入嘗試。IP 在海外。帳號名稱在 root、admin、ubuntu 之間輪流試。這就是有人跑了「自動化程式(機器人)」,對密碼進行暴力破解(Brute Force)。

「欸?我還沒被駭吧……?」

幸好沒被攻破。但面對一個站在門口一把一把試鑰匙的小偷,能說「還沒進來所以沒事」嗎?我當下立刻開始檢查伺服器的資安狀態。

擁有公開 IP 的伺服器,24 小時不停地被來自世界各地的自動化攻擊轟炸。我的伺服器也不例外。

第一步:鎖好大門 — 強化 SSH 安全

伺服器的大門是 SSH(Secure Shell)。我連到伺服器時用的就是它。問題是,駭客也想從同一扇門進來。首先要做的,就是把這扇大門補強。

變更 SSH 連接埠 (預設 22 號 → 其他編號)

SSH 預設連接埠是 22 號。駭客的自動掃描器,第一個敲的就是 22 號埠。光是改連接埠編號,就能過濾掉超過 90% 的暴力攻擊。

# 打開 SSH 設定檔
$ sudo vi /etc/ssh/sshd_config

# 變更連接埠編號 (預設 22 → 例如 2222)
Port 2222

# 重新啟動 SSH 服務
$ sudo systemctl restart sshd

打個比方,小偷通常會盯上一樓正門(22 號)。如果把入口搬到三樓的頂樓門(2222 號),大多數小偷連門在哪都找不到。

禁止 root 帳號直接登入

看日誌就知道,駭客第一個嘗試的帳號是「root」。因為 root 是 Linux 的最高管理員帳號,一旦被攻破,整台伺服器就被掌控了。

# 在 SSH 設定檔中禁止 root 直接登入
$ sudo vi /etc/ssh/sshd_config

PermitRootLogin no

現在連 root 要 SSH 登入本身都不可能了。用一般帳號登入之後,需要時再用 sudo 提升權限即可。

以 SSH 金鑰驗證取代密碼

密碼再怎麼複雜,只要自動程式嘗試數萬種組合,總有一天會被破解。最保險的方法,就是把密碼登入完全關掉,只用「SSH 金鑰(Key)」連線。

# 在自己電腦(本機)上產生 SSH 金鑰對
$ ssh-keygen -t rsa -b 4096

# 把公鑰複製到伺服器
$ ssh-copy-id -p 2222 user@my-server-ip

# 在伺服器上停用密碼登入
$ sudo vi /etc/ssh/sshd_config
PasswordAuthentication no

SSH 金鑰驗證不是「鑰匙」,而是「指紋辨識」。密碼(鑰匙)可以被複製,但只存在於我電腦上的私鑰(指紋),實際上幾乎無法複製。


第二步:築牆 — 防火牆(Firewall)

強化完大門(SSH)之後,接下來該在建築周圍築牆,控制出入口了。這就是「防火牆(Firewall)」。

伺服器總共有 65,535 個連接埠(出入口)。沒有防火牆的話,等於這六萬多扇門全部敞開。必須只開需要用的門,其餘一律鎖死。

在 Linux 上最容易上手的防火牆工具,就是「UFW(Uncomplicated Firewall)」。

# 啟用 UFW
$ sudo ufw enable

# 預設政策:進來的全部擋,出去的允許
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing

# 只開需要的連接埠
$ sudo ufw allow 2222/tcp   # SSH (變更後的連接埠)
$ sudo ufw allow 80/tcp     # HTTP
$ sudo ufw allow 443/tcp    # HTTPS

# 查看目前的防火牆狀態
$ sudo ufw status
連接埠 用途 是否開放
2222 SSH (變更後的連接埠) ✅ 允許
80 HTTP (網頁) ✅ 允許
443 HTTPS (安全網頁) ✅ 允許
22 SSH (預設,不再使用) ❌ 封鎖
其餘 全部 ❌ 封鎖

六萬多扇門中,只留下三扇開著,其餘全用磚頭封死。小偷要敲的門,本身就不存在了。

防火牆的原則很簡單:「全部關閉,只開需要的。」

第三步:通訊加密 — HTTPS

如果伺服器要對外提供網站服務,使用者與伺服器之間的通訊也必須保護。這就是「HTTPS」。

HTTP 傳送資料就像「明信片」一樣直接寄出。中途任何人都可以偷看內容。HTTPS 則是把資料放進「密封的信封」再寄出。就算被攔截,也無法讀取內容。

如果使用者在登入表單輸入的帳號/密碼,是以 HTTP 傳送的會怎樣?與你共用咖啡廳 Wi-Fi 的某個人,就能原封不動地看到這些內容。

在實務上,部署 HTTPS 最簡單的方法,就是用「Let’s Encrypt」申請免費的 SSL 憑證。

# 安裝 Certbot (Let's Encrypt 自動化工具)
$ sudo apt install certbot python3-certbot-nginx

# 申請憑證並自動套用到 Nginx
$ sudo certbot --nginx -d mydomain.com

# 測試自動更新 (憑證每 90 天需要更新一次)
$ sudo certbot renew --dry-run

只要這幾行指令,自己服務的網址就會從 http:// 變成 https://,瀏覽器網址列也會出現鎖頭圖示。等於告訴使用者:「這個網站是安全的。」


第四步:自動防禦系統 — Fail2Ban

就算改了 SSH 連接埠、設定了金鑰驗證,這世上還是有鍥而不捨的機器人。一定會有找出新連接埠、不斷嘗試連線的傢伙。

這時候派得上用場的,就是「Fail2Ban」。它是一款能自動封鎖多次登入失敗 IP 的工具。

# 安裝 Fail2Ban
$ sudo apt install fail2ban

# 設定 SSH 保護
$ sudo vi /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222
maxretry = 5
bantime = 3600
findtime = 600
設定 意義
maxretry = 5 試錯 5 次
bantime = 3600 就把該 IP 封鎖 1 小時
findtime = 600 在 10 分鐘內失敗 5 次時觸發
# 啟動 Fail2Ban
$ sudo systemctl enable fail2ban
$ sudo systemctl start fail2ban

# 查看目前被封鎖的 IP
$ sudo fail2ban-client status sshd

Fail2Ban 就像立在大門前的「監視器 + 自動鎖」。可疑人物密碼輸錯太多次,系統就會自動禁止他出入。

伺服器安全不是單一層,而是層層堆疊的安全機制。

實務建議:資安檢核清單

把目前為止設定的內容整理成檢核清單。每次架新伺服器時只要照著這份清單跑一遍,就能建立起基本的防線。

# 項目 指令/設定
1 變更 SSH 連接埠 sshd_config 中設 Port 2222
2 禁止 root 登入 PermitRootLogin no
3 切換為 SSH 金鑰驗證 PasswordAuthentication no
4 啟用防火牆 ufw enable,只允許必要連接埠
5 部署 HTTPS Let’s Encrypt + Certbot
6 安裝 Fail2Ban 登入失敗時自動封鎖 IP
7 定期更新 sudo apt update && sudo apt upgrade

第 7 項意外地重要。資安漏洞每天都在冒出來。就算把防火牆築得再牢,只要作業系統或軟體本身有洞,還是沒用。定期更新,是最基本卻也最有效的資安對策。


結語:資安不是什麼特別的事,而是一種習慣

一開始,「資安」這個字聽起來很了不起。防駭、入侵偵測、加密……感覺都是電影裡才有的東西。

但實際做過才發現,這並不需要什麼了不起的技術。變更 SSH 連接埠、開防火牆、設定金鑰驗證、裝上 Fail2Ban。幾行指令就搞定了。重要的不是「知道」,而是「去做」。

資安事故不是因為多高超的駭客技術,而是發生在連最基本措施都沒做的伺服器上。

那天之後,我每次架新伺服器,在把程式碼丟上去之前,一定先跑過這份資安檢核清單。打開門之前先檢查鎖。這就是守住一台伺服器最基本的態度。

一路走來,我們為了在 Linux 這片荒野中生存,鍛鍊了基本體能(CLI、權限、資安)。但有一個根本問題仍然沒解決:我筆電(Windows)和 Linux 伺服器的環境,根本不一樣。Java 版本不同,函式庫也不同。

有一項技術,能永遠終結「我電腦上可以跑耶?」這種藉口。下次,我們就來聊聊把環境差異徹底消除的「虛擬化與容器」。

發佈留言