前几天朋友问了我一个问题,如何让内网的机器C(仅能访问内网地址),可以访问外网(百度,google)。外网机器A可以连接vpn后,ssh至内网机器C。并且朋友暗戳戳的表示VPN软件是EasyConnect,你们公司开发的(你应该有办法吧…)
画一下拓扑图
嗯,看起来是个很常见的需求,之前只知道内网传统怎么搞(外网访问内网),这种内网访问外网倒是没尝试过,但感觉差别不大。
和朋友讨论了后,他搜到了答案。
我在本地搭了个环境,来重现下这个场景。
内网访问外网的这部分可以直接看第二部分的内容,第一部分是搭建环境时遇到所有流量都走vpn记录的解决办法。
windows split tunnel
windows default vpn的设置是所有流量都走vpn。
假设在未连接VPN时,
原始可访问的网络可访问范围是A,
而vpn内的网络可访问范围是B
那么如果使用配置,你在使用vpn后,你的可访问范围便成为了B。
这样有一些不方便,现在想实现的需求是,可访问的网络范围是A和B的并集。
Google,搜了下,参考这个回答 – Super User
操作很简单,就设置关闭默认vpn的默认路由即可
You can turn off taking over your entire connection by going to the properties of the VPN,
Networking
tab,Internet Protocol (TCP/IP)
properties,Advanced
, untickUse default gateway on remote network
. T
回答所引用的windows的官方文档也可以看下,话说这种需求有个专业词汇叫做split tunneling
测试下,
在未连接vpn时,ip为 192.168.3.56,网关为 192.168.3.1,可以访问google
PS C:\Users\14190> ping 192.168.3.1
正在 Ping 192.168.3.1 具有 32 字节的数据:
来自 192.168.3.1 的回复: 字节=32 时间=1ms TTL=64
来自 192.168.3.1 的回复: 字节=32 时间=2ms TTL=64
192.168.3.1 的 Ping 统计信息:
数据包: 已发送 = 2,已接收 = 2,丢失 = 0 (0% 丢失),
PS C:\Users\14190> curl -v www.google.com
详细信息: GET http://www.google.com/ with 0-byte payload
详细信息: received -1-byte response of content type text/html; charset=UTF-8
StatusCode : 200
通过vpn连回server端,server是一个路由器,网段是192.168.2.1/24,存在内网ip 192.168.2.20
先测试访问下vpn端的ip
PS C:\Users\14190> ping 192.168.2.1
正在 Ping 192.168.2.1 具有 32 字节的数据:
来自 192.168.2.1 的回复: 字节=32 时间=47ms TTL=64
来自 192.168.2.1 的回复: 字节=32 时间=50ms TTL=64
192.168.2.1 的 Ping 统计信息:
数据包: 已发送 = 2,已接收 = 2,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 47ms,最长 = 50ms,平均 = 48ms
Control-C
PS C:\Users\14190> ping 192.168.2.20
正在 Ping 192.168.2.20 具有 32 字节的数据:
来自 192.168.2.20 的回复: 字节=32 时间=50ms TTL=63
来自 192.168.2.20 的回复: 字节=32 时间=75ms TTL=63
来自 192.168.2.20 的回复: 字节=32 时间=60ms TTL=63
再测试访问下google
PS C:\Users\14190> curl -v www.google.com
详细信息: GET http://www.google.com/ with 0-byte payload
详细信息: received -1-byte response of content type text/html; charset=UTF-8
StatusCode : 200
StatusDescription : OK
OK,需求达成。这个时候我突然有另一个想法。
内网访问外网
vpn内的192.168.2.20,目前可访问的网段是B,如果我也想让他的可访问网段是A+B,有没有简单一点的做法呢。
参考这个回答SSH 命令的三种代理功能(-L/-R/-D),我们可以使用ssh来简单点完成。
HostA$ ssh -R HostC:PortC:HostB:PortB user@HostC
这条命令的意思是,在HostC开一个端口PortC,使所有通过HostC:PortC的流量经过ssh加密后,传回HostA,再由HostA通过HostB的PortB去访问链接。
假设我们想访问google,那么网络拓扑图大概长这样
在HostA的输入命令便是
ssh -R 0.0.0.0:30088:172.27.32.1:30088 root@192.168.2.20
其中
0.0.0.0:30088,指在HostC暴露监听的端口
172.27.32.1:30088,指HostB:PortB (本地代理)
root@192.168.2.20,UserC@HostC
在HostC测试一下
root@OpenWrt:~# curl -v -x localhost:30088 www.google.com
> GET http://www.google.com/ HTTP/1.1
> Host: www.google.com
> User-Agent: curl/7.66.0
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 302 Found
< Location: http://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=http://www.google.com.hk/&ust=1673759669988754&usg=AOvVaw2t54P3g7h-J2Xaigb_bFEm
测试通过
2023.1.18补
这里漏了一点,文中得HostB是一个本地得Proxy Server用来代理转发流量的。
那么有没有简单的工具用来做本地的Proxy呢,有的
Unix:
建议拉代码本地编译一下
#ubuntu sudo apt-get install autoconf
./autogen.sh
./configure
make
make install
一个简单的配置文件
MaxClients 10
Port 8889
Listen 0.0.0.0
Timeout 600
#Upstream http 172.27.32.1:30088
启动:/usr/local/bin/tinyproxy -d -c tinyproxy.conf
Windows: TODO..