天灾人祸,今年开年大家被迫在家远程办公。以前从来没有规划过的一些网络问题被提上了台面。我司是一个几乎不加班的公司。从来没有人被要求要在家里完成工作。我们有一些服务是内网的,同时写了一些工具供办公室的文员使用。然后被迫远程,需要解决在家里访问公司内网的要求。同时因为业务的原因还需要访问谷歌

访问公司内网服务

最常规的方案是VPN, 我对VPN不熟悉。但是在网上看到了一篇很详细的教程,刚好符合业务需求。利用softEther VPN远程访问内部网络。我试着搭建了一下。能够实现需求。用起来就是办公室里面的一台电脑一样。能够访问内网服务。能够正常使用Google. 但是我对这个不熟,不清楚如何优化它的配置。导致使用这个方案性能无比的差。连上VPN的客户端的所有请求都会经过中转服务器,在中转到内网。即使是不需要代理的请求也会被处理,这在性能上是完全无法接受的

既然是http服务,那么如果使用了域名。是很好解决的。修改DNS让映射到一个外网ip. 访问外网ip,外网再转发到内网。基本不需要在客户端上做任何修改。即使觉得创建一个域名比较麻烦,相对写死一个ip,使用xip.io,或者sslip.io 这种服务也比写死ip强。如果用域名。客户端想要访问完全可以直接修改本地Hosts

解决方案

因为客户端都是用windows,所以用了proxifier. 它支持劫持所有的客户端访问,然后使用http或者socks代理进行代理处理请求

有了代理就比较好办了。比如本机访问192.168.1.3。将访问代理到公网中转服务器,中转服务器转发到公司内网,如图所示
有几个需要注意的地方

  1. 公网转发到内网使用的是zerotier,虽然有很多种方案可以做到转发,但是我个人比较偏好zerotier。觉得比较好管理,效果也不错。其次为什么没有选择直接让本机客户端直接安装zerotier,是因为大概只有电信网络使用zerotier比较顺畅,其他比如移动,联通几乎无法使用
  2. proxifier支持http代理,但是不支持普通http代理,仅仅支持connect隧道方式(不清楚这两者的区别,可以查看最后的链接)。非常多的现成代理工具,对于普通的http请求使用的是普通代理,对于https请求使用的是隧道代理,这和要求不符合

中转服务器使用mitmproxy进行转发

1
2
3
4
5
6
7
8
9
10
11
12
import mitmproxy
from mitmproxy import http

def request(flow):
if flow.request.pretty_host.endswith("192.168.3.1"):
flow.request.host = "172.22.233.213"
else:
flow.response = http.HTTPResponse.make(
200, # (optional) status code
b"Hello World", # (optional) content
{"Content-Type": "text/html"} # (optional) headers
)

访问代理google。因为业务需求需要访问谷歌地图
这个也是使用proxifier进行代理。但是这个并不能使用http代理。因为http代理使用的是本地DNS解析,这一步就会得到错误的IP. 因此需要使用socks5代理搭配DNS远程解析(proxifier可以设置)
服务端使用的是clash, 配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
socks-port: 5553
allow-lan: true
mode: Rule
authentication:
- "xxxx:xxxx"

Proxy Group:
- name: "auto"
type: url-test
proxies:
- ss1
- ss2
- ss3

Rule:
- DOMAIN-KEYWORD,google,auto
- MATCH,REJECT

缺点

  1. 客户端需要设置,而且设置略复杂。如果使用域名代替直接写ip要好处理很多
  2. http和socks5代理都是明文, 安全性缺失

优点嘛,解决了问题,可实施性和性能都还是不错的

参考资料

http代理原理及其实现
clash