Ubuntu 網路

網路配置

改變 Hostname

修改 /etc/hostname 的內容為新主機名稱,或者採用 hostnamectl set-hostname

/etc/hostname 的內容
ubuntu

再來改調整 /etc/hosts

/etc/hosts 的內容
127.0.0.1       localhost
# 127.0.1.1       ubuntu (1)
1 至於 /etc/hosts 內的 127.0.1.1 可改為新主機名稱。但建議註掉,因為網路服務以主機名稱監聽時,其位置並不是外部的 IP 而是內部的 127.0.1.1 無法正確運作。

重開機

sudo reboot now

網路設定

執行 ifconfig (或 ip -c a) 的情況
ens32     Link encap:Ethernet  HWaddr 00:0c:29:06:dd:7e (1)
          inet addr:192.168.1.2  Bcast:192.168.1.254  Mask:255.255.255.0
1 (正常情況下) 只有一個介面是 LAN IP,確認目前工作中的介面是 ens32 該值依據主機有所不同。

關於 resolv.conf 的檔案

/etc/resolv.conf 內有 nameserver 的設置,但 /etc/resolv.conf 是依據網路管理產生,修改 resolv.conf 只在本次有作用,重啟服務將會重置。

查看內容:
cat /etc/resolv.conf

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 192.168.1.254

Ubuntu 18 / 20 網路設定

在 Ubuntu 16 網路介面的設定檔在 /etc/network/interfaces,但在 Ubuntu 18 以 netplan 管理網路介面,設定檔也改變。

Ubuntu 18 打開 /etc/network/interfaces 後,你會看到以下的說明:

# ifupdown has been replaced by netplan(5) on this system.  See
# /etc/netplan for current configuration.
# To re-enable ifupdown on this system, you can run:
#    sudo apt install ifupdown

而 Ubuntu 20 根本沒有 /etc/network/interfaces 的檔案。

得知網路設定檔的位置在 /etc/netplan,而實際的設定檔案依據安裝的版本,各有不同。

Ubuntu 18 Server

01-netcfg.yaml

Ubuntu 18 / 20 Live

00-installer-config.yaml

Ubuntu LXD / LXC 容器

50-cloud-init.yaml

雖然檔案名稱不同,但 /etc/netplan 內應該只有一個檔案。

先查看一下原始設定

cat /etc/netplan/*.yaml
# This is the network config written by 'subiquity'
network:
  version: 2
  renderer: networkd
  ethernets:
    ens32:(1)
      dhcp4: true
1 ens32 是什麼? 由 ifconfig 得知。

Ubuntu 18 / 20 修改為固定 IP

# This is the network config written by 'subiquity'
network:
  version: 2
  # renderer: networkd
  ethernets:
    ens32:
      # dhcp4: true
      addresses: [192.168.1.102/24](1)
      gateway4: 192.168.1.254
      nameservers:
        addresses: [192.168.1.254](2)
1 固定 IP 位置
2 DNS 位置

註:Yaml 文件對正確的空白字元非常挑剔,注意,關鍵字之間應放置兩個空格鍵。

Ubuntu 18 / 20 使用 br0 橋接網卡

安裝橋接套件

sudo apt install bridge-utils

顯示網路設定檔

cat /etc/netplan/*.yaml

固定 IP 範例

# This is the network config written by 'subiquity'
network:
  version: 2
  # renderer: networkd
  ethernets:
    ens32:
      dhcp4: no(1)
  bridges:
    br0:
      interfaces: [ens32](2)
      addresses: [192.168.1.102/24]
      gateway4: 192.168.1.254
      nameservers:
        addresses: [192.168.1.254]
1 ens32 的 dhcp 要設為 no 或 false,否則會在開機畫面中看到 A start job is running for wait for Network to be configured
2 bridge ens32 為實際的網路介面。

註:Yaml 文件對正確的空白字元非常挑剔,注意,關鍵字之間應放置兩個空格鍵。

DHCP 如下範例

# This is the network config written by 'subiquity'
network:
  version: 2
  # renderer: networkd
  ethernets:
    ens32:
      dhcp4: no
  bridges:
    br0:
      interfaces: [ens32]
      dhcp4: yes

Ubuntu 18 / 20 重啟網路

sudo netplan try (1)
sudo netplan apply (2)
1 try: 會檢查設定,正確時會暫時套用,並且在 120 秒以後自動回復,按下 Ctrl+C 則立即回復。
當採用 ssh 連接的終端機會斷線,不過可以由另一個 CLI 執行 ping 192.168.1.102 有回應即正常,這時以 (新的) ssh 終端機連接,執行 sudo netplan apply
那如果沒有斷線會如何? 那更好,表示運作正確 (也許應該說網路組態沒改變),按下 Enter 即可。
2 apply: 確認網路設置。

DNS 解析服務

問題表徵

DNS 有運作?

systemd-resolve --status | grep 'DNS Servers' -B 16

它在 ens32br0 或者是其他網卡有運作。

ping 的情況:

網際網路運作正確:
ping google.com

PING google.com (142.251.42.238) 56(84) bytes of data.
64 bytes from tsa01s11-in-f14.1e100.net (142.251.42.238): icmp_seq=1 ttl=116 time=10.8 ms

區域網路出錯:
ping lan1

ping: lan1: Temporary failure in name resolution

IP 當然正確:
ping 192.168.1.31

PING 192.168.1.31 (192.168.1.31) 56(84) bytes of data.
64 bytes from 192.168.1.31: icmp_seq=1 ttl=64 time=1.27 ms

nslookup 的情況:

網際網路運作正確:
nslookup google.com

Server:         127.0.0.53
Address:        127.0.0.53#53

Non-authoritative answer:
Name:   google.com
Address: 142.251.43.14
Name:   google.com
Address: 2404:6800:4012:3::200e

區域網路出錯:
nslookup lan1

Server:         127.0.0.53
Address:        127.0.0.53#53

** server can't find lan1: SERVFAIL

真正的問題是 Ubuntu 18 / 20 將 resolv.conf 符號鏈接到一個存根文件,該存根文件指向本機以進行名稱解析。 本機 DNS 名稱解析意味著系統無法提供區域網路電腦的名稱及 IP。

/etc/resolv.conf 的實際位置:

ls -la /etc/resolv.conf

lrwxrwxrwx 1 root root 39 Aug 31 06:52 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

存根文件內容:

cat /run/systemd/resolve/stub-resolv.conf

...
nameserver 127.0.0.53
options edns0 trust-ad

systemd 產生 (正確的) DNS (來自 DHCP) 的設定檔:

cat /run/systemd/resolve/resolv.conf

...
nameserver 192.168.1.254

為了讓系統使用 DNS 服務器而不是本機,將符號鏈接更改為指向 /run/systemd/resolve/resolv.conf 並不是 /run/systemd/resolve/stub-resolv.conf

鏈接至正確的 DNS 設定檔:
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

檢查鏈接是否正確:
ls -la /etc/resolv.conf

lrwxrwxrwx 1 root root 32 Dec 10 02:19 /etc/resolv.conf -> /run/systemd/resolve/resolv.conf

接著,DNS 服務器的解析開始工作。無需重新啟動或重新啟動任何服務。

若要恢復原設置,執行下列:

cd /etc
sudo ln -sf ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

檢查鏈接是否恢復:
ls -la /etc/resolv.conf

lrwxrwxrwx 1 root root 39 2022-12-10 20:00 /etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf

Ubuntu 16 網路設定

先查看一下原始設定

cat /etc/network/interfaces

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto ens32 (1)
iface ens32 inet dhcp
1 上述中只有一個 ens32 網路介面,如果有多個,執行 ifconfig 確認一下。

Ubuntu 16 修改為固定 IP

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto ens32
# iface ens32 inet dhcp

iface ens32 inet static
address 192.168.1.102
netmask 255.255.255.0
gateway 192.168.1.254
dns-nameserver 192.168.1.254

重啟網路

sudo /etc/init.d/networking restart

奇怪,執行後採用 ssh 連接的終端機怎麼沒有斷線,那到底改了沒?
ping 192.168.1.2 (更改前的 IP) 及 ping 192.168.1.102 (修改後的 IP) 都有回應,在其他主機 ping $hostname 回傳是 192.168.1.102。
原來 Ubuntu 有超能力,有時在沒有重開機之前並不會改變現有網路。

Ubuntu 16 使用 br0 橋接網卡

確認有安裝橋接套件。

dpkg -l | grep bridge-utils (1)
1 若沒有則安裝 sudo apt install bridge-utils
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
# auto ens32
# iface ens32 inet dhcp

auto br0
iface br0 inet static
address 192.168.1.102(1)
netmask 255.255.255.0
gateway 192.168.1.254
dns-nameserver 192.168.1.254
bridge_ports ens32(2)
bridge_stp off
bridge_maxwait 0
1 依據實際的網路修改。
2 bridge_ports ens32 為實際的網路介面。

修改完成後,採用重開機 sudo reboot now,若重啟網路 sudo /etc/init.d/networking restart 會出現錯誤。

建立 br0 後 ifconfig 的情況

br0    Link encap:Ethernet  HWaddr 00:0c:29:06:dd:7e
       inet addr:192.168.1.102  Bcast:192.168.1.255  Mask:255.255.255.192
       inet6 addr: fe80::20c:29ff:fe06:dd7e/64 Scope:Link
       UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
       ...

ens32  Link encap:Ethernet  HWaddr 00:0c:29:06:dd:7e
       inet addr:192.168.1.102  Bcast:192.168.1.255  Mask:255.255.255.192 (1)
       inet6 addr: fe80::20c:29ff:fe06:dd7e/64 Scope:Link
       UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
       ...
1 ens32 剛開始設置時,有時會出現跟 br0 相同的 IP 位置並沒有問題。

網路其他

Windows 的 DNS NetBIOS 錯亂
rem Clear DNS Server Cache on Windows
ipconfig/flushdns

rem Clear NetBIOS/WINS cache
nbtstat -R (1)
1 需以 系統管理員的身份 才能正確執行。

Ubuntu 連接 Windwos 網路

安裝 wins,讓 Linux 能 ping Windows hostname。

sudo apt install libnss-winbind -y
/etc/nsswitch.conf 的內容
hosts:  files dns
修改為下列
hosts:  files dns wins

Linux 存取 Windows 的共享檔案

安裝 cifs,cifs-utils 讓 Ubuntu 能存取 Windows 的共享檔案。

sudo apt install cifs-utils -y

先在 /mnt 建立共享目錄名稱:
sudo mkdir /mnt/files
sudo mkdir /mnt/share

sudo mount -t cifs //$host/share /mnt/share -o user=$user,password=$password,vers=1.0,file_mode=0777,dir_mode=0777 (1)
sudo mount -t cifs //$host/files /mnt/files -o user=$user,password=$password,vers=1.0,file_mode=0555,dir_mode=0555

強制卸載 CIFS 連接:
sudo umount -a -t cifs,nfs -l
1 $host 為 Windows 主機名或 IP,share 及 files 為 Windows 共享目錄名稱,
如 $share 可讀寫那麼將 Linux 權限設為 0777,如 $file 唯讀那麼將 Linux 權限設為 0555,
$user 為 Windows 帳戶,$password 為 Windows 帳戶密碼。
vers=1.0,解決 CIFS VFS: ioctl error in smb2_get_dfs_refer rc=-5 錯誤。

如果開機要自動掛載,編輯檔案 /etc/fstab 加入下列:

//$host/share /mnt/share cifs username=$user,password=$password,vers=1.0,file_mode=0777,dir_mode=0777
//$host/files /mnt/files cifs username=$user,password=$password,vers=1.0,file_mode=0555,dir_mode=0555

有時會在主機的主控台出現下列訊息,以 Shutdown script 來解決。

CIFS VFS: Server 192.168.1.2 has not responded in 180 seconds. Reconnecting...

Linux 存取 VMware 的 Shared folders 共享目錄

讓 Ubuntu 能存取 VMware 的 Shared folders 共享目錄。

Ubuntu 16 需安裝:
apt install open-vm-tools

配置 open-vm-tools

檢查狀態:
service open-vm-tools status

如果下列表示執行正確
active (running)

檢查版本:
/usr/bin/vmware-toolbox-cmd -v

11.0.5.17716 (build-15389592)

先在 /mnt/hgfs 建立共享目錄名稱:
mkdir /mnt/hgfs/files
mkdir /mnt/hgfs/share

顯示共享目錄名稱:
vmware-hgfsclient

share
files

已事先在 VMWare 中的 Shared folders 建立好 share files 並啟用 Folder sharing,但找不到任何檔案:
ls /mnt/hgfs/files

共享目錄找不到任何檔案

需要執行 vmhgfs-fuse 掛載:
vmhgfs-fuse -o nonempty -o allow_other .host:/files /mnt/hgfs/files
vmhgfs-fuse -o nonempty -o allow_other .host:/share /mnt/hgfs/share

檢查掛載是否正確:
ls  /mnt/hgfs/files

配置 samba

讓 Windows 辨識 Linux hostname (NetBIOS) 主機名稱及存取 Linux 共享檔案。

Samba 使用者帳戶必須要是 Linux 帳戶中的一個,Samba 使用者帳戶就是 Linux 帳戶,先建立 Linux 帳戶,可採用 Windows 帳戶名稱,登入 Samba 就不需採用另一組帳密。
另外,Samba 的密碼需個別設定,也就是說相同的帳戶,會有 Linux 的密碼及 Samba 密碼,可把 Linux 帳戶密碼改不同並不影響 Samba,但別把帳戶密碼弄的太複雜,這兩個密碼還是輸入 Windows 帳戶密碼吧!

安裝 samba:
sudo apt install samba -y

檢查版本:
samba --version

設定加入帳戶的名稱:
SambaUser=Windows帳戶名稱

輸入 linux 密碼:
sudo adduser $SambaUser --no-create-home

輸入 samba 密碼:
sudo smbpasswd -a $SambaUser (1)
1 如果出現 Failed to add entry for user test. 表示 Linux 系統並沒有該帳戶,建議你檢視一下 Linux 帳戶 是否建立錯誤。
改變 Samba 帳戶密碼
採用刪除 Samba 帳號再新增:
smbpasswd -x $SambaUser
smbpasswd -a $SambaUser

配置好 smb.conf 後,增加(刪除) Samba 帳號,怎麼 Windows 不能(還能)登入?
重啟服務即可,Samba 有時不會即時更新組態:
sudo service smbd restart

列出 Samba 帳戶:
sudo pdbedit -L -v
配置 /etc/samba/smb.conf
取消 Samba 記錄檔,找出下列註解它:
log file = /var/log/Samba/log.%m(1)

workgroup = WORKGROUP(2)

尾部加入下列:
[root]
   path = /
   writeable = yes
   valid users = $SambaUser(3)
   force user = root
   force group = root
   create mode = 0775(4)
   directory mode = 0775

[ubuntu](5)
   path = /home/ubuntu
   writeable = yes
   valid users = $SambaUser
   force user = ubuntu
   force group = ubuntu
   create mode = 0775
   directory mode = 0775
1 取消 Samba 記錄檔,找到 log file 註消它,前面加上 #
2 在中間的 workgroup,可以改為 Windows 系統中正確的 workgroup。
3 $SambaUser 請改為 Windows 的帳戶名稱 (別照貼),實際上這裡是 Linux 的帳戶, 由於前後文的原因,Linux 的帳戶名稱也就是 Windows 的帳戶名稱。valid users 可為多個 Linux 帳號,採用 , 分隔。
4 create mode 和 create mask 參數是同義詞,用哪個都可以。
5 每一個共享目錄名稱指定讀寫的目錄 (path),指定讀寫的 Linux 用戶 (force user ) 及群組 (force group), 可指定只允許某些 Linux 帳號 (valid users) 登入該共享目錄名稱。
以本例而言,$SambaUser 可讀寫 root、ubuntu 共享目錄,說明如下:
  • root (共享目錄):
    在 root (共享目錄),能讀寫所有目錄 (/),建立檔案或目錄的擁有者 (force user) 為 root,擁有群組 (force group) 為 root, 檔案權限 (create mode) 為 775,目錄權限 (directory mode) 為 775。

  • ubuntu (共享目錄):
    在 ubuntu (共享目錄),能讀寫目錄為 /home/ubuntu,建立檔案或目錄的擁有者及擁有群組為 ubuntu,檔案及目錄權限為 775。

這裡剛好可以說明,Linux 的權限跟 Windows 不同,Linux 具有擁有者及擁有群組的概念, 除非是具有 root 的權限,否則擁有權不同時將無法存取,如果以 root (共享目錄) 將檔案寫入 \\%host%\root\home\ubuntu,那麼 ubuntu 帳戶將無法讀取,因為檔案的擁有者不同。

/etc/samba/smb.conf 增加 www 共享目錄
[www]
   path = /var/www(1)
   writeable = yes
   valid users = $SambaUser
   force user = www-data
   force group = www-data
   create mode = 0775
   directory mode = 0775
1 在 www (共享目錄),能讀寫目錄為 /var/www,建立檔案或目錄的擁有者及擁有群組為 www-data,檔案及目錄權限為 775。
重啟 samba 服務
sudo service smbd restart

配置 SSH

在 SSH 服務器未配置組態時,SSH 連接到服務器時出現 SSH Permission denied 錯誤:
Permission denied (publickey).

SSH 配置的組態預設禁止以密碼及公開金鑰登錄,也就是完全禁止登錄。

/etc/ssh/sshd_config 簡要示例
#PermitRootLogin prohibit-password (1)

#PubkeyAuthentication yes (2)

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile     .ssh/authorized_keys .ssh/authorized_keys2 (3)

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no (4)
#PermitEmptyPasswords no (5)
1 允許 root 的登錄方式
2 是否允許公開金鑰登錄
3 公開金鑰檔案位置,預設值為 ~/.ssh 目錄中 authorized_keysauthorized_keys2 的檔案。
4 是否啟用密碼驗證
5 是否允許無密碼登錄

SSH 允許密碼驗證時,才能以密碼登錄。

sshd_config 啟用密碼驗證
PasswordAuthentication yes (1)
1 註釋原始的 #PasswordAuthentication no 一樣是啟用密碼驗證。

修改 sshd_config 後,需重新啟動 SSH 服務器才會套用更改 (只要改變 sshd_config 每次都要重啟服務)。

重新啟動 SSH 服務器
sudo service ssh restart
root 帳戶預設禁止登錄,以該身份登錄將會禁止。
$ssh root@my-ssh-server
root@my-ssh-server's password:
Permission denied, please try again.
sshd_config 允許 root 登錄
PermitRootLogin yes
sshd_config 跟登錄相關的設定
  • 啟用密碼驗證
    PasswordAuthentication yes

  • 允許 root 登錄
    PermitRootLogin yes

  • 允許公開金鑰登錄
    PubkeyAuthentication yes

改變 sshd_config 將 SSH 服務的連接埠改為 222223 同時監聽
Port 222
Port 223
重啟 ssh 後,檢查狀態
$sudo netstat -tlpn | grep sshd
tcp        0      0 0.0.0.0:222             0.0.0.0:*               LISTEN      47002/sshd
tcp        0      0 0.0.0.0:223             0.0.0.0:*               LISTEN      47002/sshd
tcp6       0      0 :::222                  :::*                    LISTEN      47002/sshd
tcp6       0      0 :::223                  :::*                    LISTEN      47002/sshd

SSH 服務器金鑰

本地端連接至服務器,採用密碼登錄或公鑰登錄時,本地端會判斷服務器的公鑰是否正確 (或變更),再以服務器的公鑰連接服務器,服務器也會判斷公鑰是否正確,初次認證成功後,才會繼續用戶認證,服務器的金鑰是儲存在 /etc/ssh/ssh_host_*

SSH 服務器在安裝時已經配置好金鑰,若需重新產生可按下列步驟。

重新產生 SSH 服務器金鑰
sudo rm /etc/ssh/ssh_host_* (1)
sudo dpkg-reconfigure openssh-server (2)

sudo service ssh restart
1 刪除舊的 SSH Host Keys
2 重新設定 OpenSSH Server,當看到 Configuring openssh-server 時,已預設選取 keep the local version currently installed,按下 Enter 即可。

以公開金鑰連接 SSH 服務器

登錄 SSH 服務器,採用公開金鑰,登錄不需要輸入密碼,步驟如下:

  • 服務器允許公開金鑰登錄。

  • 本地端建立金鑰。

  • 本地端將公開金鑰傳送給服務器。

修改 sshd_config 允許公開金鑰登錄 (修改後,重啟 SSH 服務)
PubkeyAuthentication yes

# 啟用密碼驗證,用戶端才能傳送公開金鑰。
PasswordAuthentication yes

本地端建立密鑰及公開金鑰。

ssh-keygen 產生金鑰參數說明 (目的是在執行時不會詢問)
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ""

-t ras           金鑰類型 rsa
-f ~/.ssh/id_rsa 指定金鑰檔案的路徑及名稱
-N ""            雙重認證密碼為空白。

-C 設定公開金鑰檔案結尾的註解,預設為「用戶@主機名稱」
產生 rsa ecdsa ed25519 密鑰 (無副檔名) 及公鑰 (副檔名為 .pub)
rm ~/.ssh/id_*
ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ""
ssh-keygen -t ecdsa -f ~/.ssh/id_ecdsa -N ""
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
合併公鑰 (.pub) 至 authorized_keys 檔案。
cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys
cat ~/.ssh/id_ecdsa.pub >> ~/.ssh/authorized_keys
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
將公開金鑰傳送給服務器
ssh-copy-id ubuntu@my-ssh-server (1)
1 需輸入密碼
在 SSH 服務主機中對應帳戶的 authorized_keys 內容會記錄用戶端的公開金鑰
$cat /home/ubuntu/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE1l9OKM6n3rLhIMmGerihH+HzwsogkwF7QFWe1p5QDH ubuntu@client1 (1)
1 ubuntu@client1 是用戶端公開金鑰的註解,在執行 ssh-keygen 產生公鑰時;註解預設為「用戶@主機名稱」。服務器中的主要是檢查公開金鑰,並不會判斷註解,註解的功能就只是個註解。
若用戶端主機名稱變更,還是能以一樣的公鑰正確連線,除非;用戶端產生不同的公鑰 (用戶端密鑰已變更) 傳送給服務器時,服務器檢查公開金鑰不同時才會增加記錄。

列示 Ubuntu 18 / 20 建立公鑰檔案後的權限情況
userhome=~

列出權限 rwx 採用下列:
ls -ld $userhome; ls -ld $userhome/.ssh; ls -l $userhome/.ssh

drwxr-xr-x 6 ubuntu ubuntu 11 2023-01-21 03:56 /home/ubuntu
drwx------ 2 ubuntu ubuntu 9 2023-01-21 16:51 /home/ubuntu/.ssh
total 9
-rw------- 1 ubuntu ubuntu  689 2023-01-21 16:51 authorized_keys
-rw------- 1 ubuntu ubuntu  227 2023-01-21 16:51 id_ecdsa
-rw-r--r-- 1 ubuntu ubuntu  183 2023-01-21 16:51 id_ecdsa.pub
-rw------- 1 ubuntu ubuntu  411 2023-01-21 16:51 id_ed25519
-rw-r--r-- 1 ubuntu ubuntu  103 2023-01-21 16:51 id_ed25519.pub
-rw------- 1 ubuntu ubuntu 1675 2023-01-21 16:51 id_rsa
-rw-r--r-- 1 ubuntu ubuntu  403 2023-01-21 16:51 id_rsa.pub

列出權限數字,採用下列:
stat -c "%a %n" $userhome/; stat -c "%a %n" $userhome/.ssh; stat -c "%a %n" $userhome/.ssh/*

755 /home/ubuntu/
700 /home/ubuntu/.ssh
600 /home/ubuntu/.ssh/authorized_keys
600 /home/ubuntu/.ssh/id_ecdsa
644 /home/ubuntu/.ssh/id_ecdsa.pub
600 /home/ubuntu/.ssh/id_ed25519
644 /home/ubuntu/.ssh/id_ed25519.pub
600 /home/ubuntu/.ssh/id_rsa
644 /home/ubuntu/.ssh/id_rsa.pub

複製密鑰及公鑰

就算 SSH 服務主機可接受多個「公開金鑰」,若在每個用戶端建立金鑰,再傳送公鑰給服務主機,太過麻煩,不打算這樣做。在 SSH 服務主機,建立密鑰及公鑰,本地端複製 SSH 服務主機的金鑰,將可在這兩部或多部之間以相同的「公開金鑰」互連,因為密鑰一樣。

實際上在主機 C1 上建立金鑰 (密鑰及公鑰),C2 複製 C1 的金鑰 (需輸入密碼), C2 再次連線 C1 時並不需要輸入密碼,也不需要傳送公鑰給 C1,因為 C1 已經有了 C1 的公鑰 (C1 在建立公鑰時已儲存至 authorized_keys 的檔案),而 C2 的公鑰恰等於 C1。另外,C1 傳送公鑰給 my-ssh-server ,C1 能以公鑰連接 my-ssh-server (authorized_keys 有 C1 的公鑰),C2 也能以相同的公鑰連接 my-ssh-server。

本地端的金鑰,只在本地端驗證金鑰是否正確。而服務器只檢查公鑰是否已存在於 authorized_keys 檔案中,如果有則允許登錄。

但如何複製? 正常的情況只有該帳戶能存取 .ssh 目錄,那麼採用 scp 登入該帳戶即可複製 .ssh 目錄。

複製其他主機金鑰
UserHost='ubuntu@192.168.1.1' (1)

cd ~
mkdir ssh2 (2)

scp $UserHost:~/.ssh/* ssh2 (3)

rm -r .ssh/* (4)
cp ssh2/* .ssh
rm -rf ssh2

chmod -R 700 ~/.ssh (5)
chmod 600 ~/.ssh/authorized_keys

ssh $UserHost (6)
1 設定來源用戶及主機
2 建立 ssh2 作為金鑰暫時儲存目錄,不能直接儲存至 .ssh 目錄,因為 scp 複製 (ssh 連接) 的過程中會存取 .ssh。
3 以 scp 複製該帳戶的金鑰至 ssh2。
4 刪除原本的 .ssh 目錄內的檔案 (保留 .ssh 目錄),並將 ssh2 檔案複製至 .ssh,最後刪除目錄 ssh2。
5 修正 .ssh 目錄及檔案權限。
6 以公鑰連接 $UserHost 不需要密碼。
複製其他用戶的 .ssh
sudo cp /home/ubuntu/.ssh/* ~/.ssh (1)
sudo chown $USER:$USER ~/.ssh -R (2)

# sudo chown $USER:$USER ~/ (3)
chmod go-w ~/
chmod -R 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# ssh ubuntu@my-ssh-server (4)
1 本例來源用戶為 ubuntu
2 $USER 為 Linux 變數,為目前登入的用戶,不需要去改。
3 如果使用者主目錄權限不正確,執行本修正。
4 連線至 ubuntu 以公鑰連接的 SSH 服務器,應該不需要密碼。

SSH 客戶端及組態

命令格式
ssh [options] [user@]hostname [command]
選項說明

-p port

指定主機的連接埠

-b bind_address

本機有多個 IP 位置時,可指定連接的 IP 位置。

-C

壓縮傳輸的資料。

-v

詳細模式,顯示執行的訊息用於偵錯連線、認證和配置問題。多個 -vv 能夠增加詳細程度,最多三個 -vvv

使用 ssh 在遠端主機執行命令
連接主機並執行 ls
ssh user@host ls -l
多行範例
ssh user@host bash << EOF
echo first command
echo second command
EOF

SSH 客戶端組態檔及順序

  1. 命令列選項

  2. ~/.ssh/config
    預設並沒有該檔案,需自行建立。

  3. /etc/ssh/ssh_config

CheckHostIP

檢查「已知主機」的主機 IP 地址。

  • no 為不檢查。

  • yes 為檢查。

不檢查時,第一次連接的訊息為:
Warning: Permanently added '**my-ssh-server**' (ECDSA) to the list of known hosts.

my-ssh-server 加入到「已知主機」,不管服務器的 IP 位置是否變更,「已知主機」只有一行。

檢查時,第一次連接至 my-ssh-server 則會以主機名稱及 IP 位置加入到「已知主機」,訊息為:
Warning: Permanently added the ECDSA host key for IP address '192.168.1.10' to the list of known hosts.

「已知主機」會有二行。當更改服務器的 IP 位置時,會出現上述警告再附加一個新行至「已知主機」,依此類推。

StrictHostKeyChecking

是否檢查「已知主機」(~/.ssh/known_hosts) 檔案中的主機公鑰。

  • yes
    公鑰不同不允許連接,也不能連接新主機。

  • no
    公鑰不同允許連接。

  • ask (預設值)
    公鑰不同不允許連接,可以連接新主機。

公鑰不同的訊息為:
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

設定值為 yes 時只能將本設定改為 noask 才能處理,因為移除「已知主機」後,無法新增主機,訊息為:Host key verification failed.。另外設定為 no 在公鑰不同時,一樣會有「公鑰不同」的訊息。

由於 .ssh/known_hos 的主機名稱為加密,無法以明文題示主機列表,只能在得知主機的名稱情況下取得資訊。

查詢是否有主機 (my-ssh-server) 的公鑰
ssh-keygen -F my-ssh-server
當「公鑰不同」時,在訊息中已提示修正方式,將「已知主機」刪除該服務主機:
ssh-keygen -f "/home/ubuntu/.ssh/known_hosts" -R "my-ssh-server"
可簡化成下列
ssh-keygen -R my-ssh-server
或者刪除 known_hosts:
rm -f ~/.ssh/known_hosts
Windows 刪除 known_hosts:
del %USERPROFILE%\.ssh\known_hosts

設定 ~/.ssh/config 不檢查 IP 及 主機公鑰。
cat > ~/.ssh/config << EOF
StrictHostKeyChecking no
CheckHostIP no
EOF

chmod 600 ~/.ssh/config
預設主機連接埠及預設登入帳號

SSH 客戶端組態檔為 ~/.ssh/config/etc/ssh/ssh_config

預設不同主機不同連接埠
Host host1
Port 221
Host host2
Port 222

執行 ssh 沒有連接埠選項時,依據 SSH 客戶端組態檔的設定。

預設 host1 登入帳號 root
Host host1
User root
Port 221

執行 ssh 沒有指定帳號時,並非以目前登入帳號而是依據 SSH 客戶端組態檔的設定。

目錄 .ssh 的權限要求

~/ 目錄其他人不可寫入,~/.ssh 目錄及檔案為 700 (註:SSH 檔案權限預設為 600,.pub 為 644,但一致為 700 並沒問題),擁有者 (Owner) 為本身帳戶。

採用下列步驟修正 SSH 檔案權限。

如果使用者主目錄的擁有者不正確先執行本修正。
sudo chown $USER:$USER ~/
修正 .ssh 檔案權限
chmod 755 ~/
chmod -R 700 ~/.ssh
列出權限數字,採用下列:
userhome=/home/ubuntu (1)
userhome=~ (2)
stat -c "%a %n" $userhome/; stat -c "%a %n" $userhome/.ssh; stat -c "%a %n" $userhome/.ssh/*
1 查詢 ubuntu 帳戶。
2 查詢本身帳戶。
755 /home/ubuntu/
700 /home/ubuntu/.ssh (1)
700 /home/ubuntu/.ssh/authorized_keys
700 /home/ubuntu/.ssh/id_ecdsa
700 /home/ubuntu/.ssh/id_ecdsa.pub
700 /home/ubuntu/.ssh/id_ed25519
700 /home/ubuntu/.ssh/id_ed25519.pub
700 /home/ubuntu/.ssh/id_rsa
700 /home/ubuntu/.ssh/id_rsa.pub
700 /home/ubuntu/.ssh/known_hosts
1 ~/.ssh 權限不一定要 700,在 Ubuntu 18 為 775 並無問題。
列出權限 rwx 採用下列:
userhome=~
ls -ld $userhome; ls -ld $userhome/.ssh; ls -l $userhome/.ssh
drwxr-xr-x 5 ubuntu ubuntu 4096 Sep 22 14:07 /home/ubuntu
drwx------ 2 ubuntu ubuntu 4096 Sep 22 14:06 /home/ubuntu/.ssh (1)
total 32
-rwx------ 1 ubuntu ubuntu  662 Sep 22 14:06 authorized_keys
-rwx------ 1 ubuntu ubuntu  227 Sep 22 14:06 id_ecdsa
-rwx------ 1 ubuntu ubuntu  174 Sep 22 14:06 id_ecdsa.pub
-rwx------ 1 ubuntu ubuntu  399 Sep 22 14:06 id_ed25519
-rwx------ 1 ubuntu ubuntu   94 Sep 22 14:06 id_ed25519.pub
-rwx------ 1 ubuntu ubuntu 1679 Sep 22 14:06 id_rsa
-rwx------ 1 ubuntu ubuntu  394 Sep 22 14:06 id_rsa.pub
-rwx------ 1 ubuntu ubuntu 1332 Sep 22 14:08 known_hosts
1 Ubuntu 18 drwxrwxr-x 並無問題。

本地端密鑰檔案權限測試
本地端的密鑰權限要為 700,改為 750:
chmod -R 750 ~/.ssh

以公鑰連接時,出現本地端的密鑰檔案權限錯誤:
ssh my-ssh-server
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0750 for '/home/ubuntu/.ssh/id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.

改回正確權限:
chmod -R 700 ~/.ssh

服務器檔案權限測試
chmod 777 ~/.ssh/authorized_keys
用戶端在登錄時並沒有顯示公鑰錯誤,要求輸入密碼
$ssh my-ssh-server
ubuntu@my-ssh-server's password:
在服務端執行查詢日誌 (取其一)
sudo journalctl -f
sudo tail -f /var/log/auth.log
在用戶端登錄時顯示下列日誌
~/.ssh/authorized_keys 權限不正確如下:
Jan 21 21:19:36 my-ssh-server sshd[1099]: Authentication refused: bad ownership or modes for file /home/ubuntu/.ssh/authorized_keys

~/ 權限不正確如下:
Jan 21 21:52:35 my-ssh-server sshd[1794]: Authentication refused: bad ownership or modes for directory /home/ubuntu

~/.ssh 權限不正確如下:
Jan 21 21:54:38 my-ssh-server sshd[1883]: Authentication refused: bad ownership or modes for directory /home/ubuntu/.ssh
在用戶端以 -v 偵錯
ssh user@host -v

~/.ssh/authorized_keys777 無法連線為 error.log,成功連線為 success.log

無法連線時,會一直繼續身份驗證 (Authentications that can continue),直到全部的公鑰失效,並無法得知是檔案權限的問題。
註:-vvv 是更細部的通訊資訊,debug1 已經跳過,不會再有 debug2debug3

diff -c error.log success.log
* 42,51 *
  debug1: Authentications that can continue: publickey,password (1)
  debug1: Next authentication method: publickey
  debug1: Offering public key: RSA SHA256:wijHZKyNlDnpWjsWOrJ1SpWtmDnXo0dF9se0XocyEZU /home/ubuntu/.ssh/id_rsa
! debug1: Authentications that can continue: publickey,password
! debug1: Trying private key: /home/ubuntu/.ssh/id_dsa
! debug1: Offering public key: ECDSA SHA256:RDesAMx/MZuCU0tPLpzwAVqgSxPQxsJCAXS1gKGpXy8 /home/ubuntu/.ssh/id_ecdsa
! debug1: Authentications that can continue: publickey,password
! debug1: Offering public key: ED25519 SHA256:mIdfzZ/RHKWrI+zoyEELflGW5jaL70VVzIUWfoOcNyM /home/ubuntu/.ssh/id_ed25519
! debug1: Authentications that can continue: publickey,password
! debug1: Next authentication method: password
--- 42,74 ----
  debug1: Authentications that can continue: publickey,password (2)
  debug1: Next authentication method: publickey
  debug1: Offering public key: RSA SHA256:wijHZKyNlDnpWjsWOrJ1SpWtmDnXo0dF9se0XocyEZU /home/ubuntu/.ssh/id_rsa
! debug1: Server accepts key: pkalg rsa-sha2-512 blen 279*
! debug1: Authentication succeeded (publickey).
1 公鑰連線失敗的偵錯訊息。
2 成功連線的偵錯訊息