← 返回文章

網路

網路網路SSHDNSSSL防火牆

網路問題的除錯順序通常是:先確認 port 有沒有在聽、再看 IP 和 DNS 解析對不對、最後才是防火牆和憑證。這頁照這個順序整理:開放 port 查詢、IP 位址、ping 與 DNS、hosts 設定、防火牆(ufw)、SSH、SCP/SFTP 檔案傳輸,以及用 Certbot 掛 SSL。範圍以 Linux 伺服器為主,部分段落含 Windows 對應指令。

開放 Port 查詢

  • 安全盤點或除錯 API/資料庫連線時,確認實際聽在哪個 port、是否只綁本機。

Linux

列出所有監聽中的 TCP port(含 process)

Code
sudo ss -tlnp
  • -t TCP
  • -l listening
  • -n 數字顯示 port(不解析服務名)
  • -p 顯示 process

僅 UDP 監聽

Code
sudo ss -ulnp

查詢特定 port 是否在監聽

Code
sudo ss -tlnp | grep :<port>
# 例:查 8080
sudo ss -tlnp | grep :8080

使用 netstat(若無 ss)

Code
sudo netstat -tlnp
sudo netstat -tlnp | grep :<port>

使用 lsof

Code
sudo lsof -i -P -n | grep LISTEN
sudo lsof -i :<port>

釋放(kill)佔用某 port 的 process

先查出 PID(例如用上面 sslsof -i :<port>),再終止:

Code
kill <pid>
# 若無法結束可強制
sudo kill -9 <pid>

Windows

列出所有監聽中的 port(含 process 名稱)

Code
Get-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, @{Name="ProcessName";Expression={(Get-Process -Id $_.OwningProcess).Name}}

僅列出 LISTENING(netstat)

Code
netstat -ano | findstr LISTENING

查詢特定 port 是否被使用

Code
netstat -ano | findstr :<port>
# 或
netstat -an | findstr ":<port>"

依 PID 查 process 名稱

Code
tasklist /fi "PID eq <pid>"

終止佔用某 port 的 process

先用 netstat -ano | findstr :<port> 取得最後一欄的 PID,再執行:

Code
taskkill /PID <pid> /F

/F 為強制結束。

Mac

列出所有監聽中的 port(含 process)

Code
lsof -i -P -n | grep LISTEN
  • -i 網路
  • -P port 以數字顯示
  • -n 不解析 hostname

僅 TCP 監聽(netstat)

Code
netstat -an -p tcp | grep LISTEN

查詢特定 port 誰在佔用

Code
lsof -i :<port>
# 例:8080
lsof -i :8080

依 PID 查 process

Code
ps -p <pid> -o comm=

釋放(kill)佔用某 port 的 process

先用 lsof -i :<port> 取得 PID,再終止:

Code
kill <pid>
# 若無法結束可強制
kill -9 <pid>

IP 位址

Linux

Code
ip -br addr show

-br 為簡潔輸出;列出介面名稱、狀態與 IP,方便腳本解析。

Code
hostname -I

輸出本機所有 IPv4 位址(空格分隔),不含介面名稱;取第一個即常用主 IP。

輸出範例(ip -br addr):

Code
lo               UNKNOWN        127.0.0.1/8
<interface>      UP             <ip>/<cidr>

UP 表示介面已啟用;/24 為 CIDR 子網路遮罩。

Windows

Code
Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notlike '*Loopback*' } | Select-Object InterfaceAlias, IPAddress

列出非 Loopback 的 IPv4 與對應介面名稱;可過濾掉 127.0.0.1。

Code
ipconfig | findstr /i "IPv4"

使用傳統 ipconfig 並過濾含 IPv4 的行,不需 PowerShell 模組。

輸出範例:

Code
InterfaceAlias IPAddress
-------------- ---------
<InterfaceAlias> <ip_address>

macOS

Code
ifconfig | grep "inet " | grep -v 127.0.0.1

ifconfig 過濾出 inet 行並排除本機回環,得到各介面的 IPv4。

Code
ipconfig getifaddr <interface>

只取得指定介面(如 en0 常見為 Wi-Fi)的單一 IPv4,適合腳本使用。

輸出範例:

Code
inet <ip> netmask <netmask> broadcast <broadcast>

有線或其它介面可能是 en1en2 等,可先用 ifconfig 看介面名稱。

Ping 與 DNS

Linux

Code
ping -c 4 <ip_or_hostname>

-c 4 只送 4 個封包後結束;可改成主機名或其它 IP,用來測網路是否通、延遲與遺失率。

Code
nslookup <domain>

查詢網域對應的 IP(A 記錄)與 DNS 伺服器;互動式可改 server 或查其它類型。

Code
dig <domain> +short

+short 只輸出解析結果(通常為 A 記錄 IP),適合腳本;不加則輸出完整 DNS 回應。

Ping 輸出範例:

Code
--- <ip_or_hostname> ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms

dig +short 輸出範例:

Code
<resolved_ip>

Windows

Code
Test-Connection -Count 4 <ip_or_hostname>

PowerShell 內建 ping,-Count 4 送 4 次;可改用 -ComputerName 主機名或 IP。

Code
Resolve-DnsName <domain>

查詢網域的 DNS 記錄(A、AAAA、NS 等);輸出包含 IP、TTL、類型,可加 -Type A 只查 IPv4。

Resolve-DnsName 輸出範例:

Code
Name                           Type   TTL   Section    IPAddress
----                           ----   ---   -------    ---------
<domain>                        A      <ttl>   Answer     <resolved_ip>
Code
nslookup <domain>

傳統 CMD 的 DNS 查詢工具,不需 PowerShell 模組,互動式可換 DNS server。

Test-Connection 輸出範例:

Code
Source        Destination     Address         Latency
------        -----------     -------
<hostname>     <ip>            <ip>             <latency_ms>

macOS

Code
ping -c 4 <ip_or_hostname>

與 Linux 相同;-c 4 送 4 個封包後停止,可測連線與延遲。

Code
nslookup <domain>

查詢網域對應 IP 與使用的 DNS 伺服器;語法與 Linux 相同。

Code
dig <domain> +short

若已安裝(內建或 Homebrew),+short 只輸出解析到的 IP,方便腳本。

ping 輸出範例:

Code
--- <ip_or_hostname> ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3012 ms

dig +short 輸出範例:

Code
<resolved_ip>

Hosts 與主機名稱

  • 裝機後要確認/變更電腦在區網顯示的名稱;搭配 網路與防火牆 一起排查連不上服務的問題。

本機靜態名稱對照(hosts)與電腦主機名稱在各平台的檔案位置、編輯方式與常用指令。格式皆為:IP、主機名/域名、別名(可多個);以空白或 Tab 分隔;# 開頭為註解。

Linux

hosts 檔(/etc/hosts

Code
cat /etc/hosts
sudo vi /etc/hosts
# 格式:IP    域名或主機名    別名
# 127.0.0.1  localhost
# <ip>  <hostname>  [<alias> ...]

變更後若解析仍舊,可視環境清除本機 DNS 快取(例如使用 systemd-resolved 時):

Code
resolvectl flush-caches

主機名(hostname)

Code
hostname
hostnamectl
sudo hostname <hostname>
sudo hostnamectl set-hostname <hostname>

選讀:搭配 ufw 限制來源 IP

僅允許特定 IP 連入某埠等設定,見 網路與防火牆(Linux、Windows、macOS)。

Code
sudo ufw allow from <allowed_ip> to any port <port> proto tcp
sudo ufw allow from <subnet> to any port <port> proto tcp

Windows

hosts 檔

路徑:C:\Windows\System32\drivers\etc\hosts(需系統管理員權限編輯)。

以系統管理員身分開啟「記事本」後開啟該檔,或使用已提升權限的終端機:

Code
notepad C:\Windows\System32\drivers\etc\hosts

格式與 Linux 相同(每行一筆:IP hostname alias)。儲存後可刷新本機 DNS 快取:

Code
ipconfig /flushdns

電腦名稱

Code
hostname
$env:COMPUTERNAME

重新命名電腦(通常需重新開機後生效):

Code
Rename-Computer -NewName "<new_name>" -Restart

macOS

hosts 檔(/etc/hosts

Code
cat /etc/hosts
sudo vi /etc/hosts
# 格式與 Linux 相同

變更後可重載 mDNS(版本不同指令可能略有差異,以下為常見寫法):

Code
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder

主機名稱(HostName / 本機主機名 / 電腦名稱)

Code
hostname
scutil --get HostName
scutil --get LocalHostName
scutil --get ComputerName

設定(依需求擇一或併用;部分需登出/重開機後才完整生效):

Code
sudo scutil --set HostName <hostname>
sudo scutil --set LocalHostName <local_hostname>
sudo scutil --set ComputerName "<顯示名稱>"

驗證(各平台共通思路)

Code
ping <hostname或別名>

getent 的 Linux 可再查:

Code
getent hosts <name>

以 HTTPS 服務測試(將埠與主機名換成你的環境):

Code
curl -I https://<hostname>:<port>

Windows 上若已安裝 curl(Windows 10 起內建),用法相同;亦可搭配 Test-NetConnection 測連線埠。

網路設定與防火牆

  • 與 本機 hosts 與主機名 搭配:先確認名稱解析,再查介面與防火牆規則。

本機 hosts 與主機名見 本機 hosts 與主機名(Linux、Windows、macOS)。

Linux

Ubuntu:netplan

Code
sudo ls /etc/netplan
# 常見檔名如 50-cloud-init.yaml
sudo cp /etc/netplan/<config>.yaml /etc/netplan/<config>.yaml.backup
sudo vi /etc/netplan/<config>.yaml

設定內容範例(YAML):

Code
network:
  version: 2
  renderer: networkd
  ethernets:
    <interface>:
      dhcp4: false
      dhcp6: false
      addresses:
        - <ip>/<cidr>
      routes:
        - to: default
          via: <gateway>
      nameservers:
        addresses: [<dns1>, <dns2>]
Code
sudo netplan apply
ip addr show <interface>

其他發行版(NetworkManager:nmcli,選讀)

Code
nmcli connection show
nmcli con mod "<connection_name>" ipv4.addresses <ip>/<cidr> ipv4.gateway <gateway> ipv4.dns "<dns1> <dns2>" ipv4.method manual
nmcli con up "<connection_name>"

防火牆:ufw

Code
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow in on lo
sudo ufw allow out on lo
sudo ufw allow from <subnet> to any port <port> proto tcp
sudo ufw status verbose
sudo ufw enable
sudo ufw status numbered

開啟/重載/檢查:

Code
sudo ufw enable
sudo ufw allow from <subnet> to any port <port> proto tcp
sudo ufw reload
sudo ufw status
sudo ufw status numbered

刪除規則:

Code
sudo ufw status numbered
sudo ufw delete [規則編號]
# 或
sudo ufw delete allow from <subnet> to any port <port>

Windows

網路(靜態 IP 範例,PowerShell)

先確認介面別名(InterfaceAlias):

Code
Get-NetAdapter | Where-Object Status -eq "Up"
Get-NetIPConfiguration

若介面原為 DHCP,改靜態前通常要先拿掉既有 IPv4 設定(請先記下原 IP/閘道/DNS):

Code
Remove-NetIPAddress -InterfaceAlias "<InterfaceAlias>" -Confirm:$false
Remove-NetRoute -InterfaceAlias "<InterfaceAlias>" -Confirm:$false -ErrorAction SilentlyContinue

寫入靜態位址、閘道、DNS:

Code
New-NetIPAddress -InterfaceAlias "<InterfaceAlias>" -IPAddress <ip> -PrefixLength <cidr_bits> -DefaultGateway <gateway>
Set-DnsClientServerAddress -InterfaceAlias "<InterfaceAlias>" -ServerAddresses <dns1>,<dns2>

改回 DHCP(依環境調整;若介面上仍有靜態 IPv4,可先移除再啟用 DHCP):

Code
Get-NetIPAddress -InterfaceAlias "<InterfaceAlias>" -AddressFamily IPv4 -ErrorAction SilentlyContinue | Remove-NetIPAddress -Confirm:$false
Set-NetIPInterface -InterfaceAlias "<InterfaceAlias>" -AddressFamily IPv4 -Dhcp Enabled
ipconfig /renew

防火牆(Windows Defender 防火牆)

Code
Get-NetFirewallProfile
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True

允許本機 TCP 埠(由外向內):

Code
New-NetFirewallRule -DisplayName "Allow TCP <port>" -Direction Inbound -Protocol TCP -LocalPort <port> -Action Allow

僅允許特定來源(例:子網路或單一 IP):

Code
New-NetFirewallRule -DisplayName "Allow TCP <port> from <source>" -Direction Inbound -Protocol TCP -LocalPort <port> -RemoteAddress <subnet_or_ip> -Action Allow

列出/移除規則:

Code
Get-NetFirewallRule -Direction Inbound | Where-Object DisplayName -like "*<keyword>*"
Remove-NetFirewallRule -DisplayName "Allow TCP <port>"

macOS

網路(networksetup

列出網路服務名稱(之後指令都要用完全一致的名稱,常見如 Wi-FiEthernet):

Code
networksetup -listallnetworkservices
networksetup -listallhardwareports

靜態 IP(子網路遮罩用點分十進位,例如 255.255.255.0,非 CIDR 前綴):

Code
sudo networksetup -setmanual "<service>" <ip> <netmask> <router>
sudo networksetup -setdnsservers "<service>" <dns1> <dns2>

改回 DHCP:

Code
sudo networksetup -setdhcp "<service>"
sudo networksetup -setdnsservers "<service>" Empty

防火牆(內建應用程式防火牆)

Code
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on

內建機制以允許/阻擋應用程式為主。若要像 Linux ufw 那樣依通訊埠、來源 IP 做細部規則,需使用 pfpfctl/etc/pf.conf),設定步驟較長,此處不展開。

SSH(Ubuntu)

Flow

Code
# 1.
sudo cat /etc/ssh/sshd_config
# 2.
sudo vi /etc/ssh/sshd_config
Port <port>
# 3.
sudo systemctl stop ssh.socket
sudo systemctl disable ssh.socket
# 4.
sudo systemctl restart ssh
# 5.
exit
# 6.
ssh -p <port> <user>@<host>

查看檔案

Code
sudo cat /etc/ssh/sshd_config

加入 port

Code
sudo vi /etc/ssh/sshd_config
Port <port>

停用 socket 啟動

Code
sudo systemctl stop ssh.socket
sudo systemctl disable ssh.socket

重新起動 ssh

Code
sudo systemctl restart ssh

確認 SSH 服務狀態

Code
sudo systemctl status ssh
# port 22 不再監聽
sudo ss -tlnp | grep :22
# port <port> 在監聽
sudo ss -tlnp | grep :<port>

快速查看 Port

Code
sudo grep -n "^Port" /etc/ssh/sshd_config

SCP / SFTP

SCP

Code
# 本機 → 遠端(檔案)
scp -P<port> -v <local_path>/<file> <user>@<host>:<remote_path>/

# 本機 → 遠端(資料夾)
scp -P<port> -v -r <local_path>/<folder> <user>@<host>:<remote_path>/

# 遠端 → 本機(檔案)
scp -P<port> -v <user>@<host>:<remote_path>/<file> <local_path>/

# 遠端 → 本機(資料夾)
scp -P<port> -v -r <user>@<host>:<remote_path> <local_path>/<folder>/

chmod +x <remote_path>/<file>

SFTP

Flow

Code
sudo groupadd sftpusers
sudo useradd -g sftpusers -d /home/<sftp_user> -s /sbin/nologin <sftp_user>
sudo passwd <sftp_user>

配置(/etc/ssh/sshd_config 或獨立檔)

  • Port 2022、Protocol 2、HostKey
  • PermitRootLogin no、PubkeyAuthentication yes、PasswordAuthentication no
  • Subsystem sftp internal-sftp
  • Match Group sftpusers:ChrootDirectory chroot_path/%u、ForceCommand internal-sftp

安裝與群組

Code
sudo apt update && sudo apt install openssh-server
sudo groupadd sftpusers
sudo groupadd sftpadmins

SSL(Certbot)

每個網域每週最多申請 5 次。

Flow:手動續約

Code
# 1. 安裝
sudo apt install certbot

# 2. DNS 驗證(需在 DNS 加 <domain> & *.<domain>)
sudo certbot certonly --manual \
  --preferred-challenges dns \
  --email <email> \
  --agree-tos \
  --no-eff-email \
  -d "*.<domain>" \
  -d "<domain>"

# 憑證會在 /etc/letsencrypt/live

# 3. 建立 nginx.conf 後 docker 開 nginx、測試、設定 crontab 自動續期
docker run -d --name <container_name> --restart unless-stopped -p <port>:<port> \
  -v <nginx_conf_path>:/etc/nginx/nginx.conf:ro \
  -v /etc/letsencrypt:/etc/letsencrypt:ro <nginx_image>

curl -k https://localhost:<port>
docker exec <container_name> nginx -s reload

# 自動續期(crontab -e)
# 0 3 * * * certbot renew --webroot -w <webroot_path> --deploy-hook "docker exec <container_name> nginx -s reload" >> /var/log/certbot-renew.log 2>&1

Flow:自動續約(需 80 port,不能用 *. domain)

Code
sudo apt install certbot
mkdir -p <webroot_path>

# 建立 nginx.conf(listen 80 + acme-challenge),再:
sudo certbot certonly --webroot -w <webroot_path> -d <domain>
docker exec <container_name> nginx -s reload

# crontab 同上;測試:sudo certbot renew --dry-run

Certbot

檢查是否已安裝

Code
which certbot
certbot --version

檢查已申請的憑證

Code
sudo certbot certificates

檢查憑證檔案位置

Code
sudo ls -la /etc/letsencrypt/live/
sudo certbot certificates | grep -A 5 "Certificate Name"

檢查憑證到期時間

Code
sudo certbot certificates | grep "Expiry Date"
sudo openssl x509 -in /etc/letsencrypt/live/[domain-name]/cert.pem -noout -dates

刪除不要的憑證

Code
sudo certbot delete --cert-name <cert_name>

測試申請 / 測試自動續期

Code
sudo certbot certonly --manual --preferred-challenges dns -d <domain> -d *.<domain> --dry-run
sudo certbot renew --dry-run

安裝

Code
sudo apt update && sudo apt install -y certbot
certbot --version

更新與複製憑證(簡要)

Code
sudo certbot certificates
sudo certbot certonly --manual --preferred-challenges dns -d <domain> -d *.<domain>
dig +short TXT _acme-challenge.<domain>
sudo openssl x509 -in /etc/letsencrypt/live/<domain>/cert.pem -noout -dates
sudo cp /etc/letsencrypt/live/<domain>/fullchain.pem <ssl_path>/fullchain.pem
sudo cp /etc/letsencrypt/live/<domain>/privkey.pem <ssl_path>/privkey.pem
sudo docker exec <container_name> nginx -s reload