SSH使用,


  • ssh的安装
      • 查看系统是否已经安装了ssh套件,或则系统是否已经启动了ssh服务
      • 安装ssh
      • 通过源代码安装ssh
      • 源码安装卸载
  • ssh配置
        • 修改SSH监听端口:
        • 禁止root用户登录:
        • 设置登录时提示信息
  • ssh命令使用
        • 通过远程主机1跳到远程主机2:
        • 通过SSH运行远程shell命令:
        • 进行端口映射:
  • ssh端口转发示例
      • 三个非常强大的命令:
        • 本地转发
        • 远程转发(或ssh反向转发)
        • 反向隧道的维持
        • 增加反向ssh的维持时间
        • 代理
        • ftp转发的例子
  • ssh密钥。
        • 生成密钥
        • 密钥分发
        • 将密钥复制进入一个名字为”authorized_keys”中。
        • 指定私钥登录有对应公钥的主机
  • 问题及处理
        • 使用密钥连接报错
        • scp指定端口

ssh的安装

查看系统是否已经安装了ssh套件,或则系统是否已经启动了ssh服务

dpkg -l openssh-server  //查看是否安装服务器端
dpkg -l openssh-client  //查看是否安装客户端

netstat -tl             //查看系统是否已经启动了ssh服务
  -t:表示tcp协议
  -l:表示listen状态

安装ssh

ubuntu系统
sudo apt install openssh-server
sudo apt install openssh-client
或centos
yum install openssh-server
yum install openssh-client

通过源代码安装ssh

从官网下载合适的版本的源码,源码安装可以选择合适的版本,远程安装需要登录上机器,替换openssh,需要安装telnet来协助,

$ sudo apt install telnetd 

完成后可以删除telnet服务
下载地址:http://www.openssh.com/portable.html

wget ttps://cloudflare.cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-6.6p1.tar.gz

下载完毕,解压缩

tar xzvf openssh-6.6p1.tar.gz

进入文件夹
用默认选项安装ssh:

./configure
make
make install

这将安装OpenSSH 二进制文件到 /usr/local/bin, 配置文件到 /usr/local/etc, 服务到/usr/local/sbin, etc.
如果报错误

 error: *** OpenSSL headers missing - please install first or check config.log *** 已经安装好了openss...

要安装libssl-dev,也就是开发包。在是ubutu的,redhat的安装openssl-devel

$ sudo apt install openssl
$ sudo apt install libssl-dev

也可以指定一个安装位置选项

./configure --prefix=/opt
make
make install

OpenSSH安装到 /opt/{bin,etc,lib,sbin}.
此处执行编译时可能报error: * zlib.h missing - please install first or check config.log *“这是由于缺少zlib-devel所致,只需安装zlib-devel即可,执行命令:yum install zlib-devel;
还有可能会包”OpenSSL headers missing - please install first or check config.log *“的错误,这是缺少openssl-devel所致,只需安装openssl-devel即可。
ubuntu需要安装libssl-dev

sudo apt install libssl-dev

重新执行./configure

正确执行配置结果

OpenSSH has been configured with the following options:
                     User binaries: /usr/local/bin
                   System binaries: /usr/local/sbin
               Configuration files: /usr/local/etc
                   Askpass program: /usr/local/libexec/ssh-askpass
                      Manual pages: /usr/local/share/man/manX
                          PID file: /var/run
  Privilege separation chroot path: /var/empty
            sshd default user PATH: /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
                    Manpage format: doc
                       PAM support: no
                   OSF SIA support: no
                 KerberosV support: no
                   SELinux support: no
                 Smartcard support: 
                     S/KEY support: no
              TCP Wrappers support: no
              MD5 password support: no
                   libedit support: no
  Solaris process contract support: no
           Solaris project support: no
       IP address in $DISPLAY hack: no
           Translate v4 in v6 hack: yes
                  BSD Auth support: no
              Random number source: OpenSSL internal ONLY
             Privsep sandbox style: seccomp_filter

              Host: x86_64-unknown-linux-gnu
          Compiler: gcc
    Compiler flags: -g -O2 -Wall -Wpointer-arith -Wuninitialized -Wsign-compare -Wformat-security -Wsizeof-pointer-memaccess -Wno-pointer-sign -Wno-unused-result -fno-strict-aliasing -D_FORTIFY_SOURCE=2 -ftrapv -fno-builtin-memset -fstack-protector-strong -fPIE 
Preprocessor flags: 
      Linker flags:  -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -fstack-protector-strong -pie
         Libraries: -lcrypto -ldl -lutil -lz -lnsl  -lcrypt -lresolv

然后执行

sudo make
sudo make install

需要重启一下

$ sudo systemctl status ssh.service
[sudo] password for gsl: 
Warning: ssh.service changed on disk. Run 'systemctl daemon-reload' to reload un
● ssh.service
   Loaded: masked (/dev/null; bad)
   Active: inactive (dead)
$ sudo systemctl start ssh.service
Failed to start ssh.service: Unit ssh.service is masked.

发现服务没起来,报 Unit ssh.service is masked.

$ sudo systemctl unmask ssh.service
Removed symlink /etc/systemd/system/ssh.service.
$ sudo systemctl start ssh.service
$ sudo systemctl status ssh.service
● ssh.service - LSB: OpenBSD Secure Shell server
   Loaded: loaded (/etc/init.d/ssh; bad; vendor preset: enabled)
   Active: active (exited) since Sat 2018-03-31 13:09:10 CST; 3s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 1025 ExecStart=/etc/init.d/ssh start (code=exited, status=0/SUCCESS)

Mar 31 13:09:10 gslvm systemd[1]: Starting LSB: OpenBSD Secure Shell server...
Mar 31 13:09:10 gslvm systemd[1]: Started LSB: OpenBSD Secure Shell server.

源码安装卸载

在解压目录

sudo make uninstall
sudo make uninstallall

ssh配置

修改SSH监听端口:

默认情况下,SSH监听连接端口22,攻击者使用端口扫描软件就可以看到主机是否运行有SSH服务,将SSH端口修改为大于1024的端口是一个明智的选择,因为大多数端口扫描软件(包括nmap)默认情况都不扫描高位端口。打开/etc/ssh/sshd_config文件并查找下面这样的行:
Port 22
去掉该行前面的# 号,然后修改端口号并重新启动SSH服务:

$ /etc/init.d/ssh restart
或
systemctl restart sshd.service

禁止root用户登录:

通常情况下,不采用直接用root用户登录到远程主机,由于root用户拥有超级权限,这样会带来安全隐患,所以,一般我们用普通用户登录,当需要管理远程主机时,再切换到root用户下。打开/etc/ssh/sshd_config文件并查找下面这样的行:

#PermitRootLogin yes

将#号去掉,然后将yes修改成no,重启ssh服务,这样就可以禁止root用户登录。

将#号去掉,然后将bannertest.txt文件的全路径替换/some/path,然后保存,重启ssh服务。当客户端登录时,就会看到bannertest.txt文件中的提示信息。

设置登录时提示信息

首先编辑一个文件,如bannertest.txt,文件内容自行定义。然后打开/etc/ssh/sshd_config文件并查找下面这样的行:

#Banner /some/path

ssh命令使用

选项

-1:强制使用ssh协议版本1-2:强制使用ssh协议版本2-4:强制使用IPv4地址;
-6:强制使用IPv6地址;
-A:开启认证代理连接转发功能;
-a:关闭认证代理连接转发功能;
-b:使用本机指定地址作为对应连接的源ip地址;
-C:请求压缩所有数据;
-F:指定ssh指令的配置文件;
-f:后台执行ssh指令;
-g:允许远程主机连接主机的转发端口;
-i:指定身份文件;
-l:指定连接远程服务器登录用户名;
-N:不执行远程指令;
-o:指定配置选项;
-p:指定远程服务器上的端口;
-q:静默模式;
-X:开启X11转发功能;
-x:关闭X11转发功能;
-y:开启信任X11转发功能。

通过远程主机1跳到远程主机2:

命令格式:

ssh -t remoteserver1 ssh remoteserver2

说明:当远程主机remoteserver2无法直接到达时,可以使用-t参数,然后由remoteserver1跳转到remoteserver2。在此过程中要先输入remoteserver1的密码,然后再输入remoteserver2的密码,然后就可以操作remoteserver2了。

通过SSH运行远程shell命令:

命令格式:

ssh -l name remoteserver ‘command

说明:连接到远程主机,并执行远程主机的command命令。例如:查看远程主机的内存使用情况。

$ ssh -l root 192.168.1.100 svmon -G

进行端口映射:

假如公司内网有台web服务器,但是只对内不对外,这样,外网就无法访问,可以用ssh进行端口映射来实现外网访问内网的web服务器。假如web服务器名为webserver,webserver可以用ssh访问到远端主机remoteserver,登录到webserver,然后用下面命令进行映射
命令格式:

ssh -R 3000:localhost:80 remote-user@remoteserver

执行完成后,在remoteserver机器上,执行netstat -an | grep 3000,查看有没有开通3000端口。并执行以下命令观察是否可以打开webserver上的网页
$ w3m http://127.0.0.1:3000
如果能打开界面,说明映射成功.但是,这只限于本机访问web服务器,即只能remoteserver机器访问webserver。因为3000端口绑定的是remoteserver机器的127.0.0.1端口。可以编辑remoteserver机器上的/etc/ssh/sshd_config文件并添加如下内容:
添加 GatewayPorts yes 内容,把监听端口3000绑定到 0.0.0.0 地址上,这样外部的所有机器都能访问到这个监听端口,然后保存退出。并重启ssh服务。完成后其它机器就可以在浏览器中输入 http://remoteserver:3000来访问webserver了。

ssh端口转发示例

三个非常强大的命令:

相关参数的解释:
-q 静默模式
-n 空设备输入重定向,如果ssh后台运行,此参数不可少。
-g 允许远程主机连接到转发端口。
在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。
-f 进入后台运行。后台认证用户/密码,通常和-N连用,不用登录到远程主机。

本地转发

ssh -C -f -N -g -L loccal_listen_port:localhost:DST_port dst_host_user@dst_Host
这个命令在localhost(主机1)执行,-L 将本地主机的监听端口转发到远端指定机器(主机3)的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时和远程主机dst_host 的 dst_tport 端口建立连接.

ssh -qngfNTL 8888:localhost:2222 root@dst_host

实现本地端口8888转发到目的主机的2222端口。

远程转发(或ssh反向转发)

ssh -qngfNTR dst_host_listen_port:localhost:localhost_port dst_host_user@dst_host
这个命令在localhost(主机2)主机上执行,把localhost_port,转发到dst_host(主机3)的dst_host_listen_port

ssh -qngfNTR 2222:localhost:22 root@dst_host

即实现把本地22端口,转发到dst_host的2222端口,这种手段实质上是由主机2向主机3 主动地建立一个SSH 隧道,将主机2 的22 端口转发到主机3的2222 端口上,只要这条隧道不关闭,这个转发就是有效的。有了这个端口转发,只需要访问主机3的2222 端口,就可反向连接主机2的22端口。

通过以上两条命令,如果dst_host(主机3)有公网ip,而执行这两条命令的的主机都位于内网,并且都可以访问dst_host,则在这两个主机之间建立一个ssh隧道。在本地转发的主机(主机1)上执行

ssh -p8888 主机2user@127.0.0.1

就可以访问主机2的22端口了。

反向隧道的维持

上面说到的ssh反向连接是不稳定的,SSH 连接是会超时关闭的,如果连接关闭,隧道无法维持,那么主机3就无法利用反向隧道穿透主机2 所在的NAT 了,为此我们需要一种方案来提供一条稳定的SSH 反向隧道。

一个最简单的方法就是autossh,这个软件会在超时之后自动重新建立SSH 隧道,这样就解决了隧道的稳定性问题你可以这样获得它:

yum install autossh

sudo apt install autossh

下面在主机2 上做之前类似的事情,不同的是该隧道会由autossh 来维持:

$ autossh -p 22 -M 6777 -qngfNTR 6766:127.0.0.1:22 主机3user@主机3

-p指定的A的ssh连接端口,这里可以不要。
-M 参数指定的端口用来监听隧道的状态,与端口转发无关。

之后你可以在主机3 上通过6766 端口访问主机2 了:

$ ssh -p 6766 主机2user@127.0.0.1

增加反向ssh的维持时间

两种方法,可选其一
1 配置服务器
打开
/etc/ssh/sshd_config
找到
ClientAliveInterval
参数,如果没有就自己加一行
数值是秒,比如你设置为540,就是9分钟.
ClientAliveInterval 540

对于
ClientAliveCountMax
指如果发现客户端没有相应,则判断一次超时,这个参数设置允许超时的次数。比如10
ClientAliveInterval 540
ClientAliveCountMax 10;

则代表允许超时 5400秒 = 90分钟

systemctl restart ssh.service

2客户端配置

sudo vi /etc/ssh/ssh_config  #或~/.ssh/config
TCPKeepAlive=yes
ServerAliveInterval 60   #客户端主动向服务端请求响应的间隔

ssh -i <key-file> -o StrictHostKeyChecking=no -o TCPKeepAlive=yes -o ServerAliveInterval=30 ubuntu@<ip>

代理

ssh -C -f -N -g -D listen_port user@Tunnel_Host
-D 指定一个本地机器 “动态的’’ 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS4 协议, 将充当 SOCKS4 服务器. 只有 root 才能转发特权端口. 可以在配置文件中指定动态端口的转发.

-C 压缩数据传输。

-N 不执行脚本或命令,通常与-f连用。

ftp转发的例子

一台服务器提供ftp服务,因为ftp传输是明文密码,如果不做ssh端口之前,我们可以通过tcpdump命令很容易的捕捉到明文信息。所以我们要对21端口进行转发,登录到ftp-server:
ftp-server# ssh -CNfg -R 2121:localhost:21 root@100.0.0.50
把本机的21端口转发到100.0.0.50的2121端口。然后登录到100.0.0.50机器,我们可以通过netstat -an|grep :2121查看端口已经侦听
100.0.0.50# ftp localhost 2121
就可以登录到ftp-server了,而且tcpdump无法捕获到有效的信息。
2121端口任意选择,只要是机器上没有占用的端口就行

来一个稍微复杂一点的,做网关的例子:
假如内网有一台提供ftp(linux,port is 2121,称为A机器)的机器,通过网关服务器(linux,port is 8888,称为B机器)进去,现在外网有一台C机器需要访问网关服务器的某个端口(port is 21)来访问内网的ftp服务器。大家可以看到,其实这就像是一个基于ssh的防火墙程序,好,下面我们来具体操作:
1、login A 机器

# ssh -CNfg -R 8888:localhost:2121 root@B机器IP

这样我们就在B机器上开了一个8888->A机器2121的端口转换,但是由于8888端口只能侦听在B主机上,因此,虽然我们已经可以在B机器上使用

# ftp localhost 8888 

来访问真正的ftp服务器,但仍然无法提供给外网的机器访问

2、login B机器

# ssh -CNfg -L 21:localhost:8888 root@localhost

这样做,是做本地机器上的21->8888端口转换,可以侦听在任何地址上的请求。
如果C机器也是一台linux机器,那也可以这样设置:

# ssh -CNfg -R 21:localhost:8888 C机器用户@C机器IP

使用C机器,
可以是linux下的ftp命令,也可以是windows下的客户端软件都可以访问B机器的21端口来连接后台真正的ftp服务器(真正的端口是2121)

ssh密钥。

在当前用户的主目录下生成密钥,并且放在一个.ssh的文件夹中。

生成密钥

    ssh-keygen -t rsa -f ~/.ssh/id_rsa
    ********提示输入密码****************
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    ********进入~/.ssh目录***************
    cd ~/.ssh/

选项

-b:指定密钥长度;
-e:读取openssh的私钥或者公钥文件;
-C:添加注释;
-f:指定用来保存密钥的文件名;
-i:读取未加密的ssh-v2兼容的私钥/公钥文件,然后在标准输出设备上显示openssh兼容的私钥/公钥;
-l:显示公钥文件的指纹数据;
-N:提供一个新密语;
-P:提供(旧)密语;
-q:静默模式;
-t:指定要创建的密钥类型。

密钥分发

ssh-copy-id命令可以把本地主机的公钥复制到远程主机的authorized_keys文件上,ssh-copy-id命令也会给远程主机的用户主目录(home)和~/.ssh, 和~/.ssh/authorized_keys设置合适的权限。

ssh-copy-id [-i [identity_file]] [user@]machine

-i:指定公钥文件
把本地的ssh公钥文件安装到远程主机对应的账户下:

ssh-copy-id -i ~/.ssh/id_rsa.pub user@server

将密钥复制进入一个名字为”authorized_keys”中。

如果公钥不是通过ssh-copy-id分发的,而是复制的,譬如,scp命令,
scp public_keys gsl371@hadoop:/home/gsl/

或者其他方式,就可以通过这个方法,追加到授权文件中,这个名字是默认的,不能改变,因为系统就是根据这个文件来判断那些机器的公钥已经保存在这里了,可以进行免钥登录。

 cat id_rsa.pub >> authorized_keys

指定私钥登录有对应公钥的主机

ssh -p 1234 gsl@10.0.0.0.16 -i ./id_rsa

问题及处理

使用密钥连接报错

错误1:

no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

1、解决方法:
添加 “-oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=+diffie-hellman-group1-sha1” 参数连接

$ssh -oHostKeyAlgorithms=+ssh-dss -oKexAlgorithms=+diffie-hellman-group1-sha1 xxx.xxx.xxx.xxx  

xxx.xxx.xxx.xxx 是具体的主机名称或主机 IP

2、修改ssh config文件

sudo gedit /etc/ssh/ssh_config 
在host下加入 
KexAlgorithms=+diffie-hellman-group1-sha1

3、还有一个办法
在用户目录下的.ssh文件夹新建一个config文件
输入

Host *
    KexAlgorithms +diffie-hellman-group1-sha1

好,问题解决了。优选方法3。
实际这些方法都没有解决最终的问题,最终的问题是因为客户端和主机之间的加密算法不一致造成的,服务器端使用了较老的加密算法,已经被淘汰,客户端加密机制不认识服务端的加密算法,最终解决方法是升级服务端的sshd的版本;如果服务端不能升级,则降低客户端的ssh版本。使其保持一致,但这个有时实现起来的还是比较难的,因为服务端不太好改变。客户端降级比较麻烦,且不安全。

错误2:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "id_rsa": bad permissions
Permission denied (publickey).

解决办法:
id_rsa在传递过程中,权限发生了扩大改变

cd ~/.ssh
chmod 600 id_rsa

错误3:
在服务器添加完公钥后报错

sign_and_send_pubkey: signing failed: agent refused operation

  这个时候我们只要执行下

eval "$(ssh-agent -s)"
ssh-add

就可以了

scp指定端口

    如果我们使用scp命令时指定的不是22端口:scp upload_file username@server时就会遇到  

      ssh: connect to host my_server port 22: Connection refused

    注意:在需要指定端口时要使用-P(大写的P),而且要紧跟在scp之后:scp -P 12349 upload_file username@server(正确)

    -P 如果放在远程主机之后会遇到这样的错误:scp upload_file username@server -P 12349(错误)

      12349: No such file or directory

     在使用时请将12349换成自己服务器对应的端口

相关内容

    暂无相关文章