现象:业务使用ssh登录对端,获取对端公钥速度很快,但是等待输入密码的时间非常慢,输入密码后登录也很快。
原因分析:
在慢机器上ssh另一个机器, ssh -v [email protected] ,可以看到一直卡在下面位置过不去
debug3: authmethod_is_enabled gssapi-with-mic
debug1: Next authentication method: gssapi-with-mic
上网查询gssapi-with-mic,是一种验证方式:
GSSAPI ( Generic Security Services Application Programming Interface) 是一套类似Kerberos 5 的通用网络安全系统接口。该接口是对各种不同的客户端服务器安全机制的封装,以消除安全接口的不同,降低编程难度。但该接口在目标机器无域名解析时会有问题
用strace ssh [email protected],查看卡住位置,可以看到查询/etc/hosts,然后打开了一个socket,取查询114.114.114.114,这个是我在/etc/resolv.conf里面设置的DNS,因此卡在了sendto函数,一直无法查询到结果。
open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=186, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f95a2d2d000
read(4, "127.0.0.1 localhost localhost."..., 4096) = 186
read(4, "", 4096) = 0
close(4) = 0
munmap(0x7f95a2d2d000, 4096) = 0
socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("114.114.114.114")}, 16) = 0
gettimeofday({1561445066, 150842}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
sendto(4, "\352\23\1\0\0\1\0\0\0\0\0\0\00213\00218\0011\00210\7in-addr\4"..., 41, MSG_NOSIGNAL, NULL, 0) = 41
poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
gettimeofday({1561445071, 154888}, NULL) = 0
poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}])
sendto(4, "\352\23\1\0\0\1\0\0\0\0\0\0\00213\00218\0011\00210\7in-addr\4"..., 41, MSG_NOSIGNAL, NULL, 0) = 41
poll([{fd=4, events=POLLIN}], 1, 5000) = 0 (Timeout)
close(4) = 0
因此,问题原因都指向了DNS查询。然而为什么ssh用的是IP而不是域名,还会导致缓慢呢,原因在于:
OpenSSH在用户登录的时候会验证IP,它根据用户的IP使用反向DNS找到主机名,再使用DNS找到IP地址,最后匹配一下登录的IP是否合法。如果客户机的IP没有域名,或者DNS服务器很慢或不通,那么登录就会很花时间。
现在问题比较明确了,解决方法如下:
方案一:直接改善DNS查询
1、将要ssh访问的IP地址与域名添加到缓慢机器的/etc/hosts中,加速查询
2、/etc/resolv.conf 中使用高速的DNS服务器,比如,我使用本地DNS服务器10.1.1.4,而不使用公共的114.114.114.114
3、检查/etc/nsswitch.conf 文件,确保有hosts: files dns行,代表查询主机会首先查询files(/etc/hosts) ,然后查询DNS(/etc/resolv.conf)。
方案二:改善ssh服务
1、查看ssh 客户端配置文件/etc/ssh/ssh_config(注意不是sshd_config),修改host:GSSAPIAuthentication no,不使用GSSAPI来鉴权。
2、修改sshd_config 添加行UseDNS no关闭ssh的dns查询,然后重启sshd(这个修改对此不大)
借鉴文章:
https://blog.csdn.net/myproudcodelife/article/details/27535261
https://blog.csdn.net/techsupporter/article/details/86553331