PKU VPN 2 - 真正实现 PKU VPN 和 Clash 兼容使用

2 个月前(已编辑)
工具 / ,
337

阅读此文章之前,你可能需要首先阅读以下的文章才能更好的理解上下文。

之前一直采用的是 Openconnect 方案,然而其总是会造成断连之后的网络丢失,于是又经过一番折腾,我终于摸索出了最完美的 VPN 兼容使用方案,其可以做到:

  • 对于所有 pku.edu.cn 域名的地址,采用北大官方代理
  • 对于所有其他地址,采用 Clash 代理

于是,我终于可以在家中同时打开 autolab.pku.edu.cn、链接 class_machine、然后还能随意的 google 了~

本文提供了两种方式:

  • 自定义 PAC 方式:操作简单适合小白
  • 自定义 Clash 订阅方式:技术要求稍高,适合爱折腾还有强迫症的(比如我

PKU VPN

不同于官方提供的 Pulse Secure 应用程序方法,我们采用部署在 Docker 内的 Openconnect 方案:

在任意一个目录下新建 pku.env 文件,填写如下内容:

USER=Your student ID
PASS=Your password
URL=vpn.pku.edu.cn
OC_ARGS=--protocol=nc

然后,在当前目录下打开终端,使用 Docker 技术,拉取镜像并启动应用:

docker pull ghcr.io/thezzisu/ocproxy:latest
docker run -d --name pku-vpn --env-file=pku.env -p 11080:1080 ghcr.io/thezzisu/ocproxy:latest

如果你没有 Docker,而且是 Mac,那我推荐使用 OrbStack ~

这会在你的 11080 端口启动一个北大 VPN 的代理服务。

自定义 PAC


shapes (2)

较为简单的方式,即通过 PAC 文件分流你的代理,在启动了 Docker 版的 PKU VPN 后,打开 系统设置 - 网络 - Wi-Fi - 详细信息 - 代理 - 自动配置代理:


Preference

填入如下 URL:

https://cdn.arthals.ink/pku_proxy.pac

或者你也可以自行部署:

function FindProxyForURL(url, host) {
    if (shExpMatch(host, '*.pku.edu.cn')) {
        return 'SOCKS5 127.0.0.1:11080';
    }
    return 'PROXY 127.0.0.1:7890';
}

自定义 Clash


shapes

较为复杂的方式,优点是一次配好再也不管,但是需要在现有订阅规则上进行修改,我使用的是 PyYaml + FastAPI 的方案,脚本如下:

# -*- encoding: utf-8 -*-
#@Author  :   Arthals
#@File    :   updater.py
#@Time    :   2023/04/28 20:42:24
#@Contact :   zhuozhiyongde@126.com
#@Software:   Visual Studio Code

import requests
import os
import yaml


def update():
    url = 'https://yoursubscribe.url'

    r = requests.get(url, timeout=10)
    data = yaml.safe_load(r.text)
    
    # 添加外部访问密码
    data['secret'] = 'xxxxxxx'

    # 添加 PKU VPN
    pku_proxy = {
        'name': 'PKU',
        'server': '127.0.0.1',
        'port': 11080,
        'type': 'socks5'
    }

    data['proxies'].insert(0, pku_proxy)

    pku_group = {'name': '🎓 PKU-VPN', 'type': 'select', 'proxies': ['PKU']}

    data['proxy-groups'].insert(0, pku_group)
    data['rules'].insert(0, 'DOMAIN-SUFFIX,pku.edu.cn,🎓 PKU-VPN')

    # 添加自定义规则
    with open('custom_rules.txt', 'r', encoding='utf-8') as f:
        rules = f.readlines()
        for rule in rules:
            rule = '%s,🔰 节点选择' % rule.rstrip("\n")
            data['rules'].insert(0, rule)

    # 添加 fallback 策略组
    fallback_group = {
        'name': '🍂 Fallback',
        'type': 'fallback',
        'proxies': ['♻️ 自动选择'],
        'url': 'http://www.gstatic.com/generate_204',
        'interval': 300
    }
    data['proxy-groups'].insert(0, fallback_group)

    # 导出 yaml 文件
    yaml.Dumper.ignore_aliases = lambda *args: True
    with open('Arthals.yaml', 'w') as file:
        yaml.dump(data, file, allow_unicode=True, default_flow_style=False)
        # print(t.encode('UTF-8'))


if __name__ == '__main__':
    try:
        update()
        os.system('pm2 restart Clash')
        os.system(
            'export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7890'
        )

    except Exception as e:
        print(repr(e))
        pass
# crontab, refresh every 6 hours
0 */6 * * * python ~/.config/clash/updater.py >> ~/.config/clash/update.log 2>&1
// PM2 Config for Clash
module.exports = {
    apps: [
        {
            name: 'Clash',
            script: './clash -f ~/.config/clash/Arthals.yaml',
        },
    ],
};
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
#@Author  :   Arthals
#@File    :   CustomAPI.py
#@Time    :   2023/09/20 00:46:28
#@Contact :   zhuozhiyongde@126.com
#@Software:   Visual Studio Code

from fastapi import FastAPI, Response

app = FastAPI()

def get_clash_config():
    # 打开/home/ubuntu/.config/clash/Arthals.yaml,并以UTF-8编码返回
    try:
        with open('/home/ubuntu/.config/clash/Arthals.yaml',
                  'r',
                  encoding='utf-8') as f:
            # print('get config success')
            resp = f.read()
            return resp
    except Exception:
        return None

@app.get('/clash')
async def get_config(token: str):
    # 检查params中是否有token,且token是否正确
    if token != 'xxxxxxx':
        return Response(status_code=403)

    return Response(content=get_clash_config(), media_type='text/plain')
// PM2 Config for CustomAPI
module.exports = {
    apps: [
        {
            name: 'CustomAPI',
            script: 'uvicorn CustomAPI:app --port 2625 --host 0.0.0.0 --reload',
        },
    ],
};

在对应文件夹启动相关 PM2 服务即可,然后再配置一个反向代理(服务器)或者直接在本地启动,然后将转换后的 URL 填入 Clash 就完成了~

然后你就可以实现身在家里网在校的代理环境啦~

Class Machine

对于 VS Code 的 Remote SSH,你需要额外配置 ssh_config 如下:

Host ICS
   HostName 162.105.31.232
   ProxyCommand nc -X 5 -x 127.0.0.1:11080 %h %p 
   Port 22222
   User u2222222222

即你需要额外配置一个 ProxyCommand 以实现代理。

Credit

感谢 @thezzisu 助教提供的灵感和实现~

评论区加载中...