[ 生活需要仪式感 ]

0%

实现网络代理模式的居家办公接入公司内网

TL; DR

简而言之,在树莓派上连接 AnyConnect 进行 VPN 登陆公司内网,同时以 TinyProxy 向局域网提供 Http(s) 代理服务,成为工作机的众多网络代理之一。如果命中了公司域名,则使用该代理进行 Git 代码提交以及内网页面处理。

同时,有更多的需求,可以以 nginx with nginx 形式,进行正向流代理或 ws 代理。


1 前言

由于深圳疫情,开始了长达接近一个月的居家办公,在家中连接公司网络成了一个难题。

  • 使用公司自有软件联完,一是索取「屏幕录制权限」有隐私风险,二是毕竟自研很多 bug,准入名单也不完善,DB 也上不去,有时还把系统卡死。
  • 使用原有的 Cisco AnyConnect 协议的 VPN 协议,且使用私有 DNS,常常连接 VPN 时,没法翻出去进行 Google 检索。

2 解决方案

2.1 思路与想法

  • 在公司找一部台式机常驻开机,架设 ss 的服务器,使用 frp 进行端口内网穿透,在家中工作机远程代理这个端口进行内网访问。
  • 在公司找一台桌面主机,开设 3389/5900 端口,使用 frp 进行端口内网穿透,家中工作机远程桌面/VNC 到宿主机,进行远程开发操作。
  • 在家中工作机,部署一个虚拟机,虚拟机内部进行 VPN 连接,共享网络到宿主进行对应操作。

2.2 思考

  1. 针对上面的思路,因为 12,需要回到办公室进行前置性工作,而我们已经居家办公又懒得回去,遂放弃。
  2. 针对上面的 3,虽然我置换了性能较强的 RMBP14,但是也不愿意白白浪费系统资源进行处理,而家中的 NAS 也因为安全隔离考虑以及太过基础而缺乏 docker 能力,遂放弃。
  3. 思前想后,只能看着抽屉里,连外壳都缺失了一片的树莓派,看看能不能让吃灰的它焕发生机。(它已经在苹果 HomeKit 生态完全接入米家设备后,因 HomeAssistant 失去了决定性作用而退役)

最终的解决方案,也就浮出水面:在树莓派中架设,联通公司的内网环境,共享网络至局域网,以便工作机连入。

3 树莓派再出发

实现上述的解决方案,这需要 2 个前提:

  1. 树莓派的 Arm 架构以及操作系统,能够支持 AnyConnect VPN 协议模式。
  2. 能够把本身环境代理出去。

3.1 树莓派连接内网环境

树莓派连入 AnyConnect Vpn Client,这个是通过了 Google 找到了一个国外的技术博客实现.

具体步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Step 1. 安装 openconnect
$ sudo apt install openconnect -y

# Step 2. 安装附加的网络管理包
$ sudo apt install network-manager-openconnect-gnome

# Step 3. 登陆 VPN
$ sudo openconnect -u username -b vpn.server.com

# Step 4. 检查是否有登陆成功
$ ip a

# Step 5. 断开 VPN
$ sudo kill -9 $(pgrep openconnect | awk '{print $1}')

简而言之,即通过开源的 OpenConnect,通过附加的插件,支持了 AnyConnect VPN 协议,并实现在树莓派的版本上进行连接。

3.2 树莓派搭建 HTTP 代理

我是通过 TinyProxy 来实现的,其是一个轻量级的 HTTP 代理实现工具,GitHub 地址有更详细的说明。

安装步骤

1
$ sudo apt-get install tinyproxy -y

安装后,会自动跑起来,以默认的 8888 端口监听服务,以 root 权限运行实例。

基本说明

TinyProxy 的基本操作命令如下

1
2
3
4
5
6
7
8
# root 模式启动服务
$ sudo service tinyproxy start

# root 模式重启
$ sudo service tinyproxy restart

# root 模式停止服务
$ sudo service tinyproxy stop

TinyProxy 的几点说明:

  • 默认监听端口 8888
  • 默认日志文件地址 /usr/var/log/tinyproxy
  • 默认的 PID 文件 /usr/var/run/tinyproxy/tinyproxy.pid
  • 默认准入 IP 地址 127.0.0.1,即只有本地能访问,要开放需要注释 Allow 这行。

具体操作

由于 TinyProxy 的监听端口无需 Root 权限进行绑定,所以可以通过转移到有权限的目录进行执行,可以以普通用户权限执行。

  1. 拷贝执行程序与配置文件
1
2
3
4
5
6
7
8
9
# 获取目前运行位置
$ which tinyproxy
-> /usr/sbin/tinyproxy

# 拷贝执行程序
$ cp /usr/sbin/tinyproxy ~/bin

# 拷贝配置文件
$ cp /etc/tinyproxy.conf ~/etc
  1. 修改对应的代理配置
  • Allow 127.0.0.1 注释掉,表示允许其他外部 IP 访问本代理
  • 将 LogFile 改为 /tmp/tinyproxy.log
  • 将 PidFile 改为 /tmp/tinyproxy.pid
  • 若需要,可以把监听端口 Port 8888 改为任意想要的端口
  1. 启动
1
2
3
4
5
# 进入执行目录
$ cd ~/bin

# 开启服务
$ ./tinyproxy -c ~/etc/tinyproxy.conf
  1. 关闭服务
1
$ killall tinyproxy
  1. 工作机配置代理

此时,在同一局域网的工作机,通过配置一个指向树莓派的 8888 端口的 HTTP 代理,即可实现对应的内网服务访问。

3.3 树莓派的数据转发

当然,有时候 HTTP 不能满足的时候,有没有更多的选择呢?

答案是有的,比如我现实情况是,需要访问一个架设在公司内网的 code-server(可视化的 WebIDE),其中需要用的 WebSocket 协议。

我是通过 pi + docker + nginx 进行处理。

使用 docker 搭建一个 nginx,专门用于正向代理转发,把对应的 code-server 的 ip:port 通过 steam 转发到本机的某个特定端口。工作机在直接访问对应的树莓派端口,即可实现对应的数据转发与浏览。

docker-copose.yml配置文件

1
2
3
4
5
6
7
8
9
10
version: '2'
services:
nginx_lb:
image: nginx:alpine
ports:
- "8084:8084"
- "8084:8084/udp"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./logs/nginx:/var/log/nginx

nginx.conf配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
user  nginx;
worker_processes 1;

events {
worker_connections 1024;
}

# 方式一:流转发模式
stream {
upstream code-svr {
hash $remote_addr consistent;
server 10.XX.XX.XX:8084; # 公司的实际地址
}
server {
listen 8004;
listen 8044 udp;
proxy_pass sit-etcd;
}
}

# 方式二:HTTP+WS 转发模式
http {
#自定义变量 $connection_upgrade
map $http_upgrade $connection_upgrade {
default keep-alive; # 默认为 keep-alive 可以支持一般 http 请求
'websocket' upgrade; # 如果为 WebSocket 则为 upgrade 可升级
}


server {
listen 8084;
# listen 8084 udp;
location / {
proxy_pass http://10.XX.XX.XX:8084; # 公司内网的实际地址
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}

}

启动方式

1
$ sudo docker-compsoe up --build -d

3.4 Git 协议无法更新-小提示

如果 git 拉代码,只能拉 https 协议,无法拉 git 协议,有 2 个解决方案:

3.4.1 方案一:开放 TinyProxy 所有端口代理

Step1 屏蔽 ConnectPort 准入名单

在 tinyproxy.conf 里 ConnectPort 443/XXX 给注释掉,表示都不发起 CONNECT 请求,基本上解决了握手问题,不过就如配置说明一样,会不够安全。

Step2 配置 git.ssh 强制走代理

- gitconfig 配置法
~/.gitconfig 中加入如下命令,表示 ssh 协议走代理

1
2
3
4
[core]
autocrlf = input
# sshCommand = ssh -o ProxyCommand=\"connect -S 127.0.0.1:7890 %h %p\" # 通过 connect 插件
sshCommand = ssh -o ProxyCommand=\"nc -x 127.0.0.1:7890 -X 5 %h %p\" # 通过 nc 插件

- ssh.config 配置法
当然,如果你先范围少一些,可以设置 ~/.ssh/config 文件

1
2
3
4
HostName e.coding.xxx.com
# IdentityFile ~/.ssh/id_rsa
#ProxyCommand nc -v -X 5 -x 127.0.0.1:7890 %h %p # SOCK5 协议代理
#ProxyCommand socat - PROXY:127.0.0.1:%h:%p,proxyport=7890 # HTTP 协议代理

3.4.2 方案二:建立一个 SSL Proxy 隧道

@dariush文章所属,自测通过。

1
2
3
4
5
6
7
8
9
10
11
12
# [step 1] create a ssh-proxy
ssh -D 9999 -qCN user@server.net

# [step 2] make git connect through the ssh-proxy
# [current script only]
export GIT_SSH_COMMAND='ssh -o ProxyCommand="connect -S 127.0.0.1:9999 %h %p"'
# OR [git global setting]
git config --global core.sshCommand 'ssh -o ProxyCommand="connect -S 127.0.0.1:9999 %h %p"'
# OR [one-time only use]
git clone -c=core.sshCommand 'ssh -o ProxyCommand="connect -S 127.0.0.1:9999 %h %p"' git@github.com:user/repo.git
# OR [current repository use only]
git config core.sshCommand 'ssh -o ProxyCommand="connect -S 127.0.0.1:9999 %h %p"'

4 后记

通过以上方式,搭建了一个树莓派的代理,可以说相当的好用:

  • 工作机通过代理策略,Google 使用自己的机场,公司的地址使用树莓派,无缝完美自动切换,而且不用污染工作机的环境。
  • 手机可以直接配置代理,只要是公司地址,也能实现 wifi 内连入,对应只浏览监控页面来说,非常实用。
  • DB 工具,连接可以通过 ssh 的方式,进行连入。
  • Git 工具,连接可以通过配置 http proxy 的方式,进行连入。

5 参考

  1. cisco-anyconnect-vpn-client-on-raspberry-pi
  2. 基于TinyProxy搭建HTTP代理服务器
  3. tinyproxy unable to forward Connect methods
  4. Tinyproxy Refused CONNECT method