ずっと前に、柠檬大佬の使用 N2N 进行异地组网的文章を見て、大変衝撃を受けましたが、N2N のデプロイ体験はあまり快適とは言えませんでした。
その後、wireguard が Linux カーネルに追加されたと聞きました。以下は wireguard の紹介です:
WireGuardは、Jason A. Donenfeld によって開発されたオープンソースVPNプログラムおよびプロトコル[1]で、Linux カーネルに基づいて実装され、Curve25519を使用して鍵交換を行い、ChaCha20を暗号化に、Poly1305をデータ認証に、BLAKE2をハッシュ関数の計算に使用します[1]。また、IPv4とIPv6の第 3 層をサポートしています[2]。WireGuard は、IPsecやOpenVPNよりも優れたパフォーマンスを得ることを目的としています[3]。
確かに、wireguard のパフォーマンスは非常に良いですが、設定が非常に煩雑です。wireguard ネットワークにデバイスを追加するには、ほぼすべてのネットワークデバイスの設定ファイルを変更する必要があり、本当に面倒です。しかし、現在は tailscale というサービスプロバイダーが wireguard に基づく 0 設定の VPN ネットワークソリューションを提供しています。
headscale は tailscale の中央管理サーバーのオープンソース版で、オープンソース版は自分でデプロイでき、接続デバイスの数に制限がないため、少し時間をかけて headscale をデプロイしました。
使用したプロジェクト#
Github/headscale
Github/headscale-ui
headscale のデプロイ#
ここでは docker-compose を使用してデプロイします。
version: '3.5'
services:
headscale:
image: headscale/headscale:latest-alpine
container_name: headscale
volumes:
- ./container-config:/etc/headscale
- ./container-data/data:/var/lib/headscale
ports:
- 27896:8080
command: headscale serve
restart: unless-stopped
headscale-ui:
image: ghcr.io/gurucomputing/headscale-ui:latest
restart: unless-stopped
container_name: headscale-ui
ports:
- 9443:443
また、nginx を使用してリバースプロキシを行い、headscale-ui と headscale を異なるドメインにデプロイしました。そのため、いくつかの CORS 処理を行う必要があります。Nginx の設定ファイルは以下のようになります。
location / {
add_header 'Access-Control-Allow-Origin' '{{UIのドメイン}}' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS,DELETE ,PUT' always;
add_header 'Access-Control-Allow-Headers' 'authorization ,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '{{UIのドメイン}}' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS,DELETE ,PUT ' always;
add_header 'Access-Control-Allow-Headers' 'authorization ,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_pass {{headscaleのアドレス}};
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_redirect default;
}
headscale-ui の設定#
headscale-ui は純粋なフロントエンドプロジェクトで、ユーザーのブラウザから直接 headscale の API インターフェースを呼び出すため、headscale コンテナ内で apikey を作成して認証を行う必要があります。
docker exec -it headscale headscale apikey create
このコマンドは apikey を作成し、それを headscale-ui の設定に入力すれば大丈夫です。この設定はローカルにのみ保存され、どこにもアップロードされないため、デバイスやブラウザを変更して headscale の設定を行う場合は、この手順を繰り返す必要があります。
ACL の設定#
headscale は ACL 機能もサポートしており、この大規模な内部ネットワーク内でデバイスがアクセスできるデバイスを制御できます。ここでは、比較的シンプルな ACL 設定ファイルを作成しました。
// ./container-config/acl.json
{
"groups": {
"group:admin": ["admin"], // 管理者ユーザー
"group:user": ["user"], // 一般ユーザー
},
"acls": [
// { "action": "accept", "src": ["*"], "dst": ["*:*"] },
{ "action": "accept", "src": ["group:admin"], "dst": ["*:*"] }, // 管理者ユーザーのデバイスはすべてのデバイスにアクセス可能
{ "action": "accept", "src": ["group:user"], "dst": ["tag:share:*","autogroup:self:*"] }, // 一般ユーザーはshareタグが付いたデバイスと自分のデバイスのみアクセス可能
],
"ssh": [
{
"action": "check",
"src": [
"autogroup:members"
],
"dst": [
"autogroup:self"
],
"users": [
"autogroup:nonroot",
"root"
]
},
],
"tagOwners": {
"tag:share": ["group:admin"],
},
}
さらに、設定ファイル内のacl_policy_path
を変更する必要があります。
acl_policy_path: "/etc/headscale/acl.json"
これで基本的には完了です。クライアントの設定については、ネット上に基本的に情報があるので、ここでは詳しくは書きません。