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 成功连接的调试消息