浅谈纯远程配置树莓派(三)

浅谈纯远程配置树莓派(三)

——SSH隧道原理范例、SSH免密码登录、自定义RSA文件名及SSH隧道的自动重启配置

前情提要:上一章探讨完了配置向导(浅谈纯远程配置树莓派(二)),让我们继续流程吧

上章收尾

树莓派的配置向导完成后,记得点击Finish,输入命令行:

sudo reboot

重启树莓派,并应用刚才的配置。
重启结束后,会发现IP地址可能产生了变化,这就需要重新探测IP了。这不科学嘛,每次都得探测一遍IP,好烦的,有没有解决途径?

当然,必须有的——
这里提供两种解决方案:
一、 在路由器中配置DHCP静态路由表,将IP地址与树莓派的MAC进行绑定。
二、 修改树莓派的网卡配置文件,使其固定IP地址。

关于一,感觉操作并不难,恩,在我的路由器上不难,其他路由器应该也是类似的,也就是进入DHCP客户端列表,在这个页面上应该有类似 绑定MAC或者之类的链接/按钮,点击即可进入绑定页面/浮层/弹窗。
应该会是一个列表页面,有添加按钮,点击后输入需要绑定的MAC以及需要对应的IP地址即可。

我们着重探讨方法二。

修改树莓派网卡配置文件,使其固定IP地址

准备工作

首先,SSH连上树莓派,依然以git提供的bash进行说明,树莓派的IP地址还是以192.168.0.2作为代指,请对号入座哟,输入命令:

ssh pi@192.168.0.2

会提示输入密码,输入配置向导菜单一中设置的密码,连上树莓派。
接着输入命令:

sudo apt-get update

这行的目的在于更新软件包的库链接信息。
执行完毕后接着输入:

sudo apt-get install vim

这行的目的在于令树莓派通过库链接信息查找并安装编辑器vim。
其中会提示消耗的空间信息,并询问是否继续安装,输入y继续即可。
安装完后我们开始配置咯。

网卡配置信息

输入命令行:

sudo vim /etc/dhcpcd.conf

这里我们采用刚才安装好的vim编辑器,当然用其他编辑器也是可以的哟。
按键盘insert键或者i键,转为插入模式,在文件末尾增加如下字符:

interface eth0
static ip_address=192.168.0.2/24
static routers=192.168.0.1
static domain_name_servers=114.114.114.114 223.5.5.5

如图所示:
浅谈纯远程配置树莓派(三)_第1张图片
被红框框选的部分即为需要填入的部分。
命令的含义依次为:

interface eth0

这行表示指定的这个配置针对哪张网卡。

static ip_address=192.168.0.2/24

这是说需要将树莓派配置成那个静态IP地址,使用CIDR(详细说明点这里查看)格式输入IP地址哟。
这里,我们还是以192.168.0.2为例进行配置。

static routers=192.168.0.1

这个步骤是设置这个配置应对的网关IP地址,需要填入路由器的IP地址哟。
因此上个步骤中,强烈建议与此IP同网段,不然可能会出现,配置失败,上不了网的情况哟。

static domain_name_servers=114.114.114.114 223.5.5.5

这行表示这个配置应对的DNS服务器地址,按需求填写吧,这里我选的一个是114的DNS,一个是阿里云的DNS,不要吐槽哈。

这里可以看到关于dhcpcd.conf的更详细配置信息
输入完毕后,按Esc键退出插入模式,后输入:

:wq

对编辑结果存盘,并退出vim编辑器。
接着输入命令:

sudo dhcpcd -x

或者输入命令:

sudo reboot

重启树莓派也可以。
稍等片刻会发现git控制台中ssh连接已经掉线了,不要当心,这表示刚才配置的静态IP已经生效啦。
重新连上树莓派。

通过SSH隧道穿内网

说到穿内网,那么就能想到很多方法,例如:
1. 通过路由器的端口映射功能,将指定IP指定端口映射给广域网
2. 通过NAT-DDNS设备或软件完成穿内网,可以参考链接:内网穿透(内网映射)NAT-DDNS
3. 通过SSH隧道/反向隧道完成穿内网
4. 通过VPN连接,搭建虚拟局域网环境完成穿内网
5. 等等其他更多方法

现在我们先探讨SSH隧道/反向隧道完成穿内网,关于路由器的端口映射功能穿内网之后再行探讨。之后也会一起研究如何搭建基于Ubuntu 中pptp服务的VPN,通过这个VPN,也能达成穿内网效果。
好,让我们开始吧。

SSH隧道穿内网的原理

为什么要穿内网

由于我们的树莓派,位于路由器之后,因此没法在广域网中通过IP:端口,例如:10.0.0.1:22 这种形式直接访问到。这个IP与端口的组合,实际访问的是路由器。我们树莓派等于被路由器给隔离开了广域网环境。因此我们需要用某种方式,可以在广域网中访问到我们的树莓派。

SSH隧道/反向隧道的原理

我们先假定一个网络拓扑结构:

机器代号 机器位置 IP地址 账户 SSH/SSHD端口 是否需要运行SSHD
A 广域网 a.com user_a 2201
B 树莓派 局域网,路由器后面 192.168.0.2 pi 2202
B2 与B同网段的机器
B可以直达B2
局域网,路由器后面 192.168.0.3 - -
C 局域网,路由器后面 10.0.0.2 user_c 2203

我们知道了没法通过IP:端口的形式访问树莓派,但是反过来却是可以的,即可以通过如上表A机器的IP:端口的形式,从树莓派访问A机器。
那么,能不能在A机器与B机器之间搭建一条通道,让满足某种特定条件的数据包,经由A机器,转发投递给B机器呢?
可以的,我们可以使用如下指令在B机器中,主动与A进行连接,并要求A将访问A的某个端口的数据,转发投递给B的一个端口。
例如:所有访问a.com:6000的数据,全部经由A,转发投递给B的2202端口,命令行为:

ssh -NfR 6000:192.168.0.2:2202 user_a@a.com -p 2201

这里会要求输入密码,请输入A机器user_a帐户的密码
这条指令的含义为:
使用user_a用户,通过端口2201在a.com机器上,打开一条隧道,隧道的参数如下:所有a.com:6000的数据转发投递至执行这条指令的机器中,并由执行这条指令的机器转交投递给192.168.0.2:2202,这条指令后不再执行其他指令,这条指令位于后台执行。
其中:

-N 表示打开隧道后,不再执行其他指令。
f 表示这条指令位于后台执行,不占用当前bash/shell。
-p 2201表示在A机器的2201端口执行
user_a 表示使用帐户user_a执行这条指令
@a.com 表示在a.com这个IP上执行这条指令
R 表示打开一条远程隧道,隧道的入口端口为6000,出口为执行指令机器。再经由执行指令机器,转交投递给192.168.0.2这个IP上的2201这个端口。

可能上面容易绕进去,让我们换一下场景。
我们依然在B上执行某一条指令,这条指令想要使得其他机器可以通过a.com:6666访问到B2机器的80端口,即192.168.0.3:80,那么指令为:

ssh -NfR 6666:192.168.0.3:80 user_a@a.com -p 2201

那么这条指令的起始点为B机器,终点为A机器的2201端口, 执行的用户名为user_a。
执行的内容为:令A将其6666端口收到的数据转发给192.168.0.3:80,其中192.168.0.3是相对于B来说的。192.168.0.3即为B2的IP啦。

实战准备

那么从以上分析可以知道,我们要搭建一条SSH反向隧道,需要存在一台A机器,这台机器我把它称之为“桥”,当然,也能叫它“代理”。
这台A机器可以是各大ISP提供的VPS,也可以是直连广域网的PC,甚至还可以是做过端口映射的某路由广域网IP:端口。
这里,我以阿里云的超小型VPS为例进行说明。
VPS为Ubuntu 16.04系统,ssh端口号为22,帐户为root。
不太建议使用延迟超过200ms以上的或者丢包率有点高的VPS,因为你会觉得很痛苦,ssh操作相当迟缓,甚至操作丢失、断连。
为了避免记忆VPS的IP地址,可以准备一个域名,将域名的A记录绑定到VPS的IP上。
假定绑定的域名为:vps.a.com。

实战

在打开SSH反向隧道前,我们要对VPS做一个配置,使其允许远程主机连接本地的转发端口。
通过ssh,连上VPS,输入命令行(请事先安装vim编辑器):

sudo vim /etc/ssh/sshd_config

在其末尾加上:

GetwayPorts yes

记得保存退出哟。


现在,我们在树莓派上执行指令:

ssh -NfR 6000:localhost:22 root@vps.a.com -p 22

那么再其他任意机器上,都能通过:

ssh pi@vps.a.com -p 6000

连入树莓派。例如可以通过手机(使用流量哟)连入树莓派的ssh。

实战中遇到的问题

这里遇到了两个问题,希望可以解决,并提高体验。
问题一:每次都得输入VPS的密码,好烦啊。
问题二:ssh -R开通的反向隧道不稳定,有时候就断开了,连不上了。

好的,我们先解决第一个问题:

SSH免密登录

生成公钥和私钥

所谓的免密登录,当然不是免除身份验证,而是通过某种形式,让其自动校验我们的身份,免除输入密码的繁琐操作。
我们先在树莓派中输入命令:

ssh-keygen -t rsa

接着会出如下提示:

Generating public/private rsa key pair.
Enter file in which to save the key (/home/pi/.ssh/id_rsa):

这是要求输入生成的公钥以及私钥的存放路径和文件名。
一般来说,建议路径为~/.ssh/自定义文件名_rsa,其中~部分需要输入绝对路径。

当然,不输入也是可以的,那么会默认在~/.ssh/id_rsa生成私钥,公钥则为id_rsa.pub。
按回车确认,接下来会询问:

Enter passphrase (empty for no passphrase)
Enter same passphrase again

这两个表示是否要给私钥设置一个密码。后者为验证密码。
假如不想设置密码,直接回车即可。
我们假定生成的文件名分别为:
/home/pi/.ssh/pi_rsa 和 /home/pi/.ssh/pi_rsa.pub,没有密码。

接下来,我们要将公钥复制到VPS,作为身份验证参照。可以使用命令行:

ssh-copy-id -i /home/pi/.ssh/pi_rsa.pub -p 22 root@vps.a.com

最后输入一次密码,即可将公钥配置给VPS。
由于ssh默认使用id_rsa作为私钥文件名,进行查询登录,我们用的是自定义私钥名称,因此需要做一些其他设置。

自定义私钥名称的配置

在树莓派中输入:

sudo vim ~/.ssh/config

来为当前用户创建一个自定义ssh配置表,在vim中按i或者Insert键,进入插入模式,键入如下内容:

Host vps
HostName vps.a.com
Port 22
User root
IdentityFile ~/.ssh/pi_rsa

其中:
Host 表示HostName的别名
HostName 表示VPS的域名或者ip地址
Port 表示VPS的ssh端口号
User 表示当前证书对应的用户名
IdentityFile 表示需要使用私钥证书文件的路径
键入完毕后,按ESC退出插入模式。接着键入 :wq 回车 来保存刚才录入的配置。
可以输入命令进行尝试:

ssh -p 22 root@vps

或者

ssh -p 22 root@vps.a.com

假如提示yes/no请输入yes。会发现它不再询问密码了,免密登录成功。

接下来,我们来解决第二个问题,提高反向隧道的稳定性,当断连的时候,树莓派自动的重新开启反向隧道。

使用AutoSSH来保证SSH反向隧道的稳定性

首先连上树莓派,接着执行命令行:

sudo apt-get install autossh openssh-server

安装autossh组件。

安装完毕,即可使用命令行:

autossh -M 0 -N -R 6000:localhost:22 root@vps.a.com -i /home/pi/.ssh/pi_rsa -p 22

来自动打开反向隧道。
这样即可通过vps.a.com:6000连入树莓派啦。
不过这里又存在一个问题:万一树莓派重启了的话,这条命令就失效了,怎么办?

将AutoSSH配置为Service,让其开机就自动运行

好,我们来解决上一个问题。
连上树莓派,输入命令行:

sudo vim /lib/systemed/system/autossh.service

在创建的文件中,键入如下内容:

[Unit]
Description=autossh
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=pi
EnvironmentFile=/etc/default/autossh
ExecStart=
ExecStart=/usr/bin/nohup /usr/bin/sudo /usr/bin/autossh $SSH_OPTIONS
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

需要注意的几个点:

  1. Wants与After都要有,也都必须这么写,不然服务可能会启动失败的。这两条指示该服务需要连入网络才执行,没连入网络的情况下,请求连入网络
  2. Description表示这个服务的注解,可以随意写
  3. User这个表示树莓派的用户名。
  4. EnvironmentFile=/etc/default/autossh这个表示载入/etc/default/autossh文件作为环境变量
  5. ExecStart这个为什么写成两行,是发现了写一行会各种坑,两行比较稳定。至于到底是什么原因导致的,未知
  6. 其中 ExecStart=/usr/bin/nohup /usr/bin/sudo /usr/bin/autossh $SSH_OPTIONS为什么要写这么长。恩,这是因为这个服务执行的指令希望:

    1. 在后台执行
    2. 提权为root执行
    3. 用$SSH_OPTIONS变量来指定具体的执行参数,这样就不需要频繁的停止服务、重新注册服务、启动服务了。只需要重新启动服务就可以使得配置生效了。
  7. WantedBy 假如有其他组也想自动执行这个服务,依次往下增加即可。

补充说明,其中第5条找到一个解释为:

Notice that there are two ExecStart in our unit file. They are not typos. In order to allow this unit file to be included by another unit file, we have to clear ExecStart before specifying a new command.

保存退出后,接着执行指令,来创建/etc/default/autossh这个环境变量文件:

sudo vim /etc/default/autossh

在其中键入:

AUTOSSH_POLL=60
AUTOSSH_FIRST_POLL=30
AUTOSSH_GATETIME=0
AUTOSSH_PORT=0
AUTOSSH_PIDFILE="/var/run/autossh.pid"
SSH_OPTIONS="-N -R 6000:localhost:22 -i /home/pi/.ssh/pi_rsa [email protected] -p 22"

这里需要注意的在于AUTOSSH_PIDFILE要写,而且名字最好与service的名字一样,便于service跟踪状态。
SSH_OPTIONS中为autossh的具体命令行。
保存退出。
接着执行指令:

sudo ln -s /lib/systemd/system/autossh.service /etc/systemd/system/autossh.service

用于给服务做个软链接,接着就可以输入命令行:

sudo systemctl enable autossh
sudo systemctl start autossh

来开启服务了。
输入:

sudo systemctl status autossh

可以查询服务的状态,假如看到出现如下的字样,则表示执行成功拉:

autossh.service - Auto SSH Tunnel
Loaded: loaded (/lib/systemd/system/autossh.service; enabled)
Active: active (running) since 六 2017-04-15 16:59:06 CST; 3s ago
Main PID: 2527 (sudo)
CGroup: /system.slice/autossh.service
|-2527 /usr/bin/sudo /usr/bin/autossh -N -R 6000:localhost:22 -i /home/pi/.ssh/pi_rsa [email protected] -p 22
|-2535 /usr/lib/autossh/autossh -N -R 6000:localhost:22 -i /home/pi/.ssh/pi_rsa [email protected] -p 22
`-2546 /usr/bin/ssh -L xxx:127.0.0.1:xxx -R xxx:127.0.0.1:xxx -N -R 6000:localhost:22 -i /home/pi/.ssh/pi_rsa -p 22 [email protected]

其中xxx表示随机生成的端口号。
接下来可以试试:

ssh pi@vps.a.com -p 6000

假如成功连上了的话,则表示autossh搭建完毕咯。

补充:
假如做完ssh免密后直接开始搭建autossh的服务,那么可能会失败,需要先手动的执行一次命令行:

autossh -M 0 -N -R 6000:localhost:22 root@vps.a.com -i /home/pi/.ssh/pi_rsa -p 22
sudo kill -9 $(pidof autossh)

会提示询问yes/no,输入yes即可。会失败的原因就出现在需要输入yes/no上面了。
重新开启服务后,查询服务状态,应该就正常咯。

预告:xrdp的配置以及通过autossh隧道使得xrdp穿内网。
待续…

你可能感兴趣的:(树莓派)