简介

日常开发过程中,会遇到一些情况需要和对端机构或公司进行联调。此时有可能会需要访问对端机构内部的一些网页或API。

正规流程中,要访问内网,如果对端机构有VPN服务,应该是申请一个VPN来进行操作,这种方式比较安全可靠。但实际操作过程中,可能对端机构没有VPN服务,或者走VPN流程繁琐。此时如果你有对端机构中某个内网Linux机器的ssh登陆权限,而且该Linux机器可以可以访问相关网页或者API,则可以通过ssh tunnel的方式,临时来访问对端机构的内部资源。

接下来,通过使用两台EC2来模拟内网环境,来介绍如何在Mac机器上使用ssh tunnel访问内网资源。

搭建说明

搭建模拟用的EC2

首先,开启两台EC2,一台用来模拟ssh的跳板机(Jumpbox),一台用来模拟内部网页服务器(HttpServer)。

基本信息如下:

Instance Public IP Private IP SG Name SG Rule
Jumpbox 34.220.122.63 172.31.17.27 jumpbox-sg SSH From 0.0.0.0/0
HttpServer 52.33.58.113 172.31.21.213 HttpServer SSH from 0.0.0.0/0, HTTP from jumpbox-sg

其中Jumpbox的SecurityGroup只允许ssh登陆,HttpServer开放ssh,并开放HTTP端口为只允许Jumpbox的SG访问。

登陆HttpServer,设置一个简易的httpd服务

1
2
3
4
5
6
7
8
# 安装httpd
sudo yum install httpd -y
# 建立一个最简单的page
sudo echo "<h1> Page From `curl http://169.254.169.254/latest/meta-data/local-ipv4` </h1>" > /var/www/html/index.html
# 启动http服务
sudo systemctl start httpd.service

在Jumpbox中测试使用curl,可以成功获取到index.html的内容,为<h1> Page From 172.31.21.213 </h1>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[ec2-user@ip-172-31-17-27 ~]$ curl -vL http://172.31.21.213
* Rebuilt URL to: http://172.31.21.213/
* Trying 172.31.21.213...
* TCP_NODELAY set
* Connected to 172.31.21.213 (172.31.21.213) port 80 (#0)
> GET / HTTP/1.1
> Host: 172.31.21.213
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sat, 15 Sep 2018 06:39:46 GMT
< Server: Apache/2.4.34 ()
< Upgrade: h2,h2c
< Connection: Upgrade
< Last-Modified: Sat, 15 Sep 2018 06:27:16 GMT
< ETag: "23-575e3081098b7"
< Accept-Ranges: bytes
< Content-Length: 35
< Content-Type: text/html; charset=UTF-8
<
<h1> Page From 172.31.21.213 </h1>
* Connection #0 to host 172.31.21.213 left intact
[ec2-user@ip-172-31-17-27 ~]$

本地设置

在本地电脑上,先使用ssh -D建立一个本地到Jumpbox的ssh tunnel,然后设置浏览器使用该链接来访问对端的内网服务。

搭建ssh tunnel

打开本地Terminal,在命令行中创建ssh tunnel。ssh有三种方式创建tunnel,分别对应了参数-D,-L-R。详细用法可参照SSH原理与运用(二):远程操作与端口转发, 此处使用-D即可。

ssh -D参数的man说明如下:

1
2
3
4
5
6
7
8
9
10
-D [bind_address:]port
Specifies a local ``dynamic'' application-level port forwarding. This works by allocating a socket to listen to port on the local side, optionally bound to the speci-
fied bind_address. Whenever a connection is made to this port, the connection is forwarded over the secure channel, and the application protocol is then used to deter-
mine where to connect to from the remote machine. Currently the SOCKS4 and SOCKS5 protocols are supported, and ssh will act as a SOCKS server. Only root can forward
privileged ports. Dynamic port forwardings can also be specified in the configuration file.
IPv6 addresses can be specified by enclosing the address in square brackets. Only the superuser can forward privileged ports. By default, the local port is bound in
accordance with the GatewayPorts setting. However, an explicit bind_address may be used to bind the connection to a specific address. The bind_address of
``localhost'' indicates that the listening port be bound for local use only, while an empty address or `*' indicates that the port should be available from all inter-
faces.

使用如下命令,创建隧道

1
2
# ssh -D bind_port -i 登陆instance的private_key 用户名@public_ip
$ ssh -D 1234 -i OregonKeyPairsInCarlshenCnpem.pem ec2-user@34.220.122.63
设置Firefox

设置Firefox来使用刚建立的ssh tunnel, 打开Firefox的【首选项】页面,选择【网络代理】, 在链接设置页面,选择“手动代理配置”,SOCKS主机一栏填入127.0.0.1,端口填入ssh -D绑定的端口,我这边设置的是端口1234。

Firefox设置截图
firefox_socks_settings

此时,通过浏览器,就可以成功访问到内网HttpServer中的网页了。

internal_access_from_firefox

设置Terminal来访问内网

在Terminal中也可以设置proxy来让http和https的流量走设置好的ssh proxy。

在打开新的Terminal中,输入如下命令让本terminal中的http和https流量走设置好的ssh tunnel。

1
export http_proxy=socks5://127.0.0.1:1234;export https_proxy=socks5://127.0.0.1:1234;

使用curl,可以成功访问HttpServer中的网页。

1
2
3
[carlshen@carl-186 ~]$ curl http://172.31.21.213
<h1> Page From 172.31.21.213 </h1>
[carlshen@carl-186 ~]$

Reference

留言