一、背景
要想从本地访问远程 Linux 服务器,通常会使用一些 SSH 工具,但有时也希望程序脚本中通过 SSH 命令让远程 Linux 服务器执行一些脚本,本篇文章介绍 SSH 的基本原理,以及如何免密通过 SSH 命令 执行远程 服务器上的某些命令。
二、知识点
1、SSH 原理
1) 基于口令认证远程
说明:
- “服务端的公钥指纹存放到known_hosts文件中”:客户端从服务端接受到公钥之后,直接获取了公钥指纹,先会和本地 known_hosts 文件做对比,若该公钥指纹存在文件中,则不会向用户提示确认信息,否则需要用户确认,是否连接服务端;
第一次远程服务器,控制台会显示:
上图显示会自动把对端信息写入到 known hosts 文件中,输入密码成功远程之后退出,查看客户端 known_hosts 文件中的内容如下:
有的操作系统的客户端第一次远程会显示:
上图显示是要用户确认是否远程到服务端。
针对上述的第一种情况,非第一次登陆就不会出现那个 warning:
显然直接要求输入密码。
2) 基于公钥认证远程(免密)
2、SSH 配置
SSH 的 配置文件 在 /etc/ssh 目录下,linux 环境中 可以看到该目录下有2个配置文件:
1) sshd_config
# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. # This sshd was compiled with PATH=/usr/local/bin:/usr/bin # The strategy used for options in the default sshd_config shipped with # OpenSSH is to specify options with their default value where # possible, but leave them commented. Uncommented options override the # default value. # If you want to change the port on a SELinux system, you have to tell # SELinux about this change. # semanage port -a -t ssh_port_t -p tcp #PORTNUMBER # Port 55555 # sshd 服务启动的时候,使用的远程端口 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress :: HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key # Ciphers and keying #RekeyLimit default none # Logging #SyslogFacility AUTH SyslogFacility AUTHPRIV #LogLevel INFO # Authentication: #LoginGraceTime 2m PermitRootLogin yes # 需要设置成 yes ,客户端才能用 root 账号远程 #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 #PubkeyAuthentication yes # The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 # but this is overridden so installations will only check .ssh/authorized_keys AuthorizedKeysFile .ssh/authorized_keys #AuthorizedPrincipalsFile none #AuthorizedKeysCommand none #AuthorizedKeysCommandUser nobody # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #HostbasedAuthentication no # Change to yes if you don't trust ~/.ssh/known_hosts for # HostbasedAuthentication #IgnoreUserKnownHosts no # Don't read the user's ~/.rhosts and ~/.shosts files #IgnoreRhosts yes # To disable tunneled clear text passwords, change to no here! #PasswordAuthentication yes #PermitEmptyPasswords no PasswordAuthentication yes # Change to no to disable s/key passwords #ChallengeResponseAuthentication yes ChallengeResponseAuthentication no # Kerberos options #KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosGetAFSToken no #KerberosUseKuserok yes # GSSAPI options GSSAPIAuthentication yes GSSAPICleanupCredentials no #GSSAPIStrictAcceptorCheck yes #GSSAPIKeyExchange no #GSSAPIEnablek5users no # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will # be allowed through the ChallengeResponseAuthentication and # PasswordAuthentication. Depending on your PAM configuration, # PAM authentication via ChallengeResponseAuthentication may bypass # the setting of "PermitRootLogin without-password". # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and ChallengeResponseAuthentication to 'no'. # WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several # problems. UsePAM yes #AllowAgentForwarding yes #AllowTcpForwarding yes #GatewayPorts no X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes #PermitTTY yes #PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes #UseLogin no #UsePrivilegeSeparation sandbox #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 #ClientAliveCountMax 3 #ShowPatchLevel no #UseDNS no #PidFile /var/run/sshd.pid #MaxStartups 10:30:100 #PermitTunnel no #ChrootDirectory none #VersionAddendum none # no default banner path #Banner none #可以指定具体文件路径,该文件中存放成功登录该服务器的提示语 # Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE AcceptEnv XMODIFIERS # override default of no subsystems Subsystem sftp /usr/libexec/openssh/sftp-server # Example of overriding settings on a per-user basis #Match User anoncvs # X11Forwarding no # AllowTcpForwarding no # PermitTTY no # ForceCommand cvs server
上图为成功登录的提示
2) ssh_config
# $OpenBSD: ssh_config,v 1.30 2016/02/20 23:06:23 sobrado Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for # users, and the values can be changed in per-user configuration files # or on the command line. # Configuration data is parsed as follows: # 1. command line options # 2. user-specific file # 3. system-wide file # Any configuration value is only changed the first time it is set. # Thus, host-specific definitions should be at the beginning of the # configuration file, and defaults at the end. # Site-wide defaults for some commonly used options. For a comprehensive # list of available options, their meanings and defaults, please see the # ssh_config(5) man page. # Host * # ForwardAgent no # ForwardX11 no # RhostsRSAAuthentication no # RSAAuthentication yes # PasswordAuthentication yes # HostbasedAuthentication no # GSSAPIAuthentication no # GSSAPIDelegateCredentials no # GSSAPIKeyExchange no # GSSAPITrustDNS no # BatchMode no # CheckHostIP yes # AddressFamily any # ConnectTimeout 0 # StrictHostKeyChecking ask # IdentityFile ~/.ssh/identity # IdentityFile ~/.ssh/id_rsa # IdentityFile ~/.ssh/id_dsa # IdentityFile ~/.ssh/id_ecdsa # IdentityFile ~/.ssh/id_ed25519 Port 55555 # 这里默认的是22 ,若是在 sshd_config 文件中更改了端口,又想在ssh命令远程的时候不指定端口的话,这里需要更改成 和 sshd_config 中 Port 一样的端口值,否则无法不指定端口进行远程 # Protocol 2 # Cipher 3des # Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc # MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160 # EscapeChar ~ # Tunnel no # TunnelDevice any:any # PermitLocalCommand no # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h # # Uncomment this if you want to use .local domain # Host *.local # CheckHostIP no Host * GSSAPIAuthentication yes # If this option is set to yes then remote X11 clients will have full access # to the original X11 display. As virtually no X11 client supports the untrusted # mode correctly we set this to yes. ForwardX11Trusted yes # Send locale-related environment variables SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE SendEnv XMODIFIERS
3、SSH远程登录
1)使用默认的端口和root 用户
ssh 用户名@服务器IP |
2)指定SSH端口和用户进行登录
#在服务端添加测试用户 #创建测试用户 useradd testa #修改测试用户登录密码,这里密码修改成了 testa passwd testa #在客户端使用测试用户帐号远程登录服务端 ssh -p 22 testa@10.19.214.146 |
服务端执行结果:
客户端远程服务端执行结果:
4、SSH单向免密登录
服务端信息:
A:10.19.214.146
B:10.19.214.145
1) 使用默认的端口和 root 用户进行免密登录 (A免密登录B)
前提: A 和 B 均使用了 root 账号登录,并进行下列操作
- 在A上生成公钥/私钥
- 将A上的公钥文件拷贝到B上
- 在B上将从A同步过来的公钥写入到authorized_keys 文件中
- 在A上远程B
A上执行的操作:
ssh-keygen -t rsa scp id_rsa.pub root@10.19.214.145:~/.ssh |
B上执行的操作:
cd /root/.ssh touch authorized_keys cat id_rsa.pub >> authorized_keys |
在A上执行远程B的命令:
ssh root@10.19.214.145 'pwd' |
2) 指定端口和用户进行免密登录
这里以 两个服务器的 ssh 端口 一致为前提来进行示范。
146 服务器上创建testa用户,145 服务器上创建testb 用户,下面以在 145 上面创建 testb 为例:
#添加 testb用户 useradd testb #修改用户 testb 的密码 passwd testb # 在 /home 下可以看到 testb 文件夹 ll /home |
146/145 两台服务器上分别为 testa estb,测试 146 在当前登录用户为 testa 的情况下,使用 testb 账号信息登录 145
- 在A上生成公钥/私钥
- 将A上的公钥文件拷贝到B上
- 在B上将从A同步过来的公钥写入到authorized_keys 文件中
- 在A上远程B
A上执行:
#在A上执行 su testa ssh-keygen -t rsa cd /home/testa/.ssh #在B上执行 su testb mkdir mkdir /home/testb/.ssh #在A上执行 scp id_rsa.pub testb@10.19.214.145:~/.ssh chmod 700 /home/testa/.ssh/ #在B上执行 cd /home/testa/.ssh touch authorized_keys cat id_rsa.pub >>authorized_keys chmod 700 /home/testb/.ssh/ chmod 600 /home/testb/.ssh/authorized_keys #在A上执行 ssh testb@10.19.214.145 'pwd' #测试远程 |
A成功免密远程登录到B
PS: 在上面的示例中仍然使用了默认SSH端口进行远程,若要指定SSH的某个端口 可以在远程的时候 使用 -p <端口> 选项。
5、SSH 双向免密登录
服务端信息:
A:10.19.214.146
B:10.19.214.145
1) 使用默认的端口和 root 用户进行互信
前提: A 和 B 均使用了 root 账号登录,并进行下列操作
a) A 信任 B,免密登录B
具体操作参考上面章节: 4、SSH单向免密登录 1) 使用默认的端口和 root 用户进行免密登录,但在 4 1) 操作中直接将A的公钥文件同步到B的.ssh/id_rsa.pub 文件中,建议重命名,否则会覆盖 B自己本身的公钥文件
至此 A信任B,A可以远程B
b) B 信任A。免密登录A
该操作流程实际上和 a) 相反
上面 两张 图显示 A、B 机可以互相远程
2) 指定端口和用户进行互信
这里以 两个服务器的 ssh 端口 一致为前提来进行互信示范。
操作方式和上面基本雷同,只是 A、B 机的命令都要在对应用户下操作 ,同时 .ssh 下的文件是在 /home/用户 下
a) A 免密远程 B
此时 在 A 上用 testa 可以使用 testb 账号免密远程到 B
b) B 免密远程 A
参考:
https://www.cnblogs.com/ftl1012/p/ssh.html
https://www.cnblogs.com/viplanyue/p/12700775.html