マルチユーザーセットアップ(Ubuntu)を使用しています(異なるTTYで同時にログインしているユーザー)。
nordvpn connect
を使用して1つのアカウントからNordVPNに接続すると、すべてのユーザーがそのVPN経由でインターネットに接続されます。
ユーザーのネットワークをどうにかして分離する方法。つまり、VPNに接続すると、現在のユーザーのみが影響を受け、そのユーザーのすべての接続でVPNを使用する必要があります。
nordvpn
はopenvpn
の単なるラッパーであり、openvpn
を使用して直接接続することが可能であるため、純粋なopenvpn
ソリューションも役立ちます。Sudo
を介してrootアクセスできます。ユーザーが異なるユーザースペースを使用している状況:
デフォルトでは、ユーザースペースはネットワークを分離する( netns )ので、nordvpn connect
は他のユーザースペースには影響しませんが、これはLinuxでのユーザーシステムのデフォルトの機能ではないため、別のセットアップが必要です。各ユーザーのネットワークを分離するためのユーザー空間。また、ネットワークインターフェイスは、単一の名前空間ブリッジまたはvethインターフェイスにのみ存在し、ユーザー空間間のトラフィックをトンネルするために使用できます。
ユーザーが同じユーザースペースを使用している状況:
Linuxユーザーシステムは同じネットワークシステムの下に残ります。一方のユーザーがwifiに接続している場合、ネットワークカードはルートレベルでセットアップされ、デフォルトのセットアップでネットワークを使用しているすべてのユーザーが共有されるため、もう一方のユーザーはその接続から恩恵を受けます。 。
VPN接続は新しい仮想インターフェイス(tunまたはtap)で行われ、メインネットワークインターフェイス(wifiまたはeth0)にリンクされます... vpn接続が初期化されると、tun/tapインターフェイスが作成され、VPNサーバーに接続されますトンネルを作成しますが、これはすべての接続がVPNインターフェースを介してトンネルされることを意味しません。クラシックなVPN接続を確立するために、最初に接続が仮想インターフェースで初期化され、次にルートが使用されます。 が追加され、すべての接続が強制的にVPNインターフェースを経由するようになり、これはroutingと呼ばれます。
これらの情報を知っておくと、解決策はルーティングなしでVPN接続を開始し、ユーザーごとに個別にルーティングをセットアップすることです。 VPNを必要としないユーザーには変更は必要ありません。 VPNを使用する必要があるユーザーのために、iptables/ip-routeを使用して特別なルーティングを追加する必要があります。つまり、VPNインターフェースはセットアップされますが、デフォルトのインターフェースにはなりません(デフォルトのVPNルーティングルールがプッシュされないため)。
VPNのデフォルトの状況:[Connect Command]> [Create-Tun/Tap]> [Connect Tun/Tap]> [Route to Make Tun/Tap as Default Interface]
ルートなしのVPN:[Connect Command]> [Create-Tun/Tap]> [Connect Tun/Tap]
VPNとカスタムルート:[Connect Command]> [Create-Tun/Tap]> [Connect Tun/Tap]then[カスタムルート]を手動または自動で追加します
「ルート」ステップを使用せずにvpnに接続してから、カスタムルートをプッシュ/セットアップします。これは、iptables/ip-routeまたはVPN confセットアップファイルを使用して行うことができます。
デフォルトゲートウェイ/ルートをプッシュせずにopenvpnを構成する方法:
Vpn confファイルを編集して、route-nopull
ディレクティブを追加します。 (nordvpn
コマンドを使用してアクセス可能なopenvpn confファイルを使用する場合は、必要に応じて編集できます。それ以外の場合は、openvpnまたはネットワークマネージャーを使用してvpnに接続する必要があります)
特定のLinuxユーザーに特定のインターフェースを使用します:
このガイド は、あなたが達成したいのとまったく同じことを達成しています。それ以外の場合 これらの回答 詳細な代替案を示します。
部分的な回答(問題の詳細が必要):
「通常の」インターネット接続とNordVPNインターネット接続を区別する1つの方法は、ネットワーク名前空間を作成し、この名前空間でnordvpn
を開始してから、この名前空間でこのVPNを使用するすべてのプロセスを開始することです。
詳細は、使用方法によって異なります。
NordVPNを常に起動する単一のユーザーがいる場合、ログイン時にそのネットワーク名前空間を作成し、そのネットワーク名前空間でそのユーザーのすべてのプロセスを開始することもできます。その結果、そのユーザーは「通常の」インターネット接続を利用できなくなります。
「通常の」インターネット接続とNordVPN接続の両方を使用したいユーザーが複数いる場合は、その名前空間を作成し、その中でNordVPNを起動し、追加のアプリケーションを起動できるターミナルをユーザーに提供するスクリプトを作成できます。たぶん、この名前空間でWebブラウザのようなアプリケーションをすでに起動しているかもしれません。このスクリプトはconnect
コマンドを置き換えます。
要件が何であるかに応じて、それを行う方法はおそらく他にもたくさんあります。質問を編集して、要件/状況を説明してください。
ネームスペースを作成するには、root権限が必要です。つまり、スクリプトをsetuid-rootにする必要があります(スクリプトにバグがある場合はセキュリティ上の問題になる可能性があります)。ユーザーにSudo
アクセス権を付与する必要がある場合もあります。
この問題は、既存の設定全体、プロバイダー独自の設定を変更する可能性、サポートする実際のvpnタイプ、および多少複雑な設定を受け入れるかどうかに応じて、さまざまな方法で対処できると思います。
NordVPNサービスに固有のソリューションの場合、nordvpn
コマンドは必ずしもOpenVPNを使用する必要はなく、IPSecまたはPPTP/L2TPを使用する可能性があるため、サポートを依頼することもできます。
ただし、NordVPNサービスと完全に互換性があるという一般的なOpenVPNソリューションの場合、最善のアプローチは、ポリシールーティングを使用することです。
しかし、最初に、名前空間への関心を見て、これらを使用した可能なアプローチに関する私の意見を述べたいと思います。
確かに名前空間を使用することで、ユーザー間のネットワーキングの真の分離が得られます。OpenVPNだけでなく、あらゆるタイプのVPNの一般的なソリューションであるという主な顕著な利点があります。
ただし、問題の問題はunshare
またはip netns exec
コマンドを使用して簡単に対処できるものではないため、設定に必要なツールは多くのLinuxディストリビューションでは一般的にインストールされません。これらは、ユーザーの既存のセッション全体ではなく、そのコマンドセッション以降で実行されるプロセスに対してのみ新しい名前空間の可視性を許可します。
また、必要なツールをインストールして必要な方法でセットアップしたとしても、同じ物理ネットデバイスを使用し、UNIXを共有しながら、各ユーザーを独自のネットワーク名前空間に分離するために、システムを慎重にセットアップする必要があります。ローカルホストで実行されているドメインソケットとサービス。ブリッジ(またはmacvlans)、サブネットの設定、アドレスの割り当て、場合によってはNAT化、その他の複雑さ。それはおそらく可能ですが、それをまっすぐにすることは単純ではない可能性があり、私は元の問題よりはるかに複雑だと思います。
したがって、ルーティングポリシーアプローチに戻ると、ベースソリューションは、おそらく最も単純で実用的なものであり、ほとんどの一般的なユースケースに十分であり、またはより洗練されたバリアントに挑戦する前の出発点として、個別のユーザーのUIDに基づくルーティングポリシーを介して検索される、各ユーザーのトンネルごとのルーティングテーブル。
次の主要な特性があります。
iptables
コンパニオンルールが必要ですSudo
を介して実行したプロセス(これらはUID 0で実行されるため)や、setuidコマンドやアプリケーションをルートとして実行することは識別できません。これらは、通常のデスクトップシナリオにはほとんど当てはまりませんが、発生する可能性があり、意図したとおりに処理されません(つまり、トラフィックの一部がVPNに送信されません)。すべては2つのヘルパースクリプトで処理できます。 1つはbyOpenVPNで使用され、もう1つはrunで使用されますopenvpn
自体。
標準のOpenVPNはip
コマンドを使用して、tun/tapデバイスに設定し、VPNプロバイダーによってプッシュされたルートをインストールします。問題は、デフォルトでip
コマンドがシステム全体で使用されるメインルーティングテーブルで動作するため、そのすべてのユーザーが含まれることです。
ただし、OpenVPNでは、適用する必要がある設定に使用する別のコマンドを指定できるため、ip
のラッパーを提供するだけで、さまざまなルーティングテーブルで動作します。
このような(仮にmyip.sh
という名前の)ラッパースクリプトは次のようになります。
#!/bin/bash -
my_session="$(ps -p $$ -o sid --no-header)" || exit 1
real_uid="$(ps -p $$ -o ouid --no-header || ps -p $my_session -o ruid --no-header || echo 0)"
real_ip_cmd=/sbin/ip
if [ $real_uid -ne 0 ] && [[ "$1" = ro* ]] ; then
! [ $2 ] && exec $real_ip_cmd "$1" list table $real_uid
[[ "$2" =~ ^([adcfls]|rep).*$ ]] && exec $real_ip_cmd "$1" "$2" table $real_uid "${@:3}"
fi
exec $real_ip_cmd "$@"
最初の2行は、OpenVPNを実行している実際のUIDを取得しようとするものです。そのUIDをテーブルIDとして使用します。このようにして、各ユーザーはvpnを開始するときに独自のルーティングテーブルを持ちます。
if-then-fi
ブロックはroute
設定の呼び出しをキャッチし(ip
コマンドの短縮された明確なキーワードを受け入れる機能を模倣する)、openvpnから渡されたすべてのコマンドの前にtable
オプションは、ユーザーの実際のUIDと等しいIDを保持します。他のすべてのip
コマンド(つまり、route
以外)はそのまま通過します。
もう1つのスクリプトはopenvpn
コマンドをラップし、ユーザーが生成したトラフィックを個別のテーブルに従ってルーティングするように設定します。このラッパースクリプトの要点は、プロバイダー独自の構成ファイルに含めることができ、シームレスな統合を可能にします。これは、vpnを非対話的に(たとえば、ブート時に)確立したい場合に役立ちます。ただし、代わりにこのラッパースクリプトを使用することで、構成ファイルをいじる必要がなくなります。そのため、このバージョンを提示することにしました。
したがって、そのような単一のラッパースクリプトは次のようになります。
#!/bin/bash
my_session="$(ps -p $$ -o sid --no-header)" || exit 1
real_uid="$(ps -p $$ -o ouid --no-header || ps -p $my_session -o ruid --no-header || echo 0)"
[ $real_uid -eq 0 ] && { echo "will not run for UID 0" >&2 ; exit 1; }
remove_tagging() {
iptables -t mangle -D OUTPUT -m owner --uid $real_uid -j MARK --set-mark $real_uid
ip rule del fwmark $real_uid
ip route flush table $real_uid
} 2>/dev/null
trap 'remove_tagging' EXIT
source <(ip route | sed "s/^/ip route add table ${real_uid} /")
(
ip -o monitor | grep -qm 1 '^[0-9]\+: tun[0-9]\+[[:blank:]]\+inet '
ip rule add fwmark $real_uid lookup $real_uid
iptables -t mangle -A OUTPUT -m owner --uid $real_uid -j MARK --set-mark $real_uid
) &
openvpn --iproute myip.sh --config tunnel-config.ovpn
最初の3行は、ユーザーの実際のUIDを試行して取得するために再び機能し、取得できない場合は続行されません。
次に、スクリプトからEXITで実行する関数があります。この関数は、次のサブシェルによって設定された設定を削除します。
ただし、最初に、現在のメインルーティングテーブル全体をユーザー用の個別のテーブルにコピーします。
次に、OpenVPNによってtunX
デバイスがセットアップされるのを待機するサブシェルを実行し、その後、ユーザーが生成したトラフィックをマークするルーティングルールとiptables
コンパニオンルールを追加しますオン。ユーザー名とパスワードを要求する必要がある場合に備えてOpenVPNをフォアグラウンドで実行する必要があるため、これをバックグラウンドで実行します。
source
コマンド、サブシェル(ip -o monitor
パイプラインなし)、およびremove_tagging
関数は、vpn構成ファイルで(それぞれ)up
、route-up
、route-pre-down
オプション。そうすることで、このラッパースクリプトを完全に取り除くことができます。
最後に、実際のopenvpn
コマンドを実行し、独自のmyip.sh
スクリプトをコマンドとして使用してネットワークをセットアップするように指示します。
可能性のあるわずかなバリエーションは、ルーティングでip
の代わりにuidrange
オプションを使用するiproute2パッケージの最新バージョン(fwmark
コマンドを提供)を使用することによる可能性があります。ルール。
したがって、このようなバリアントはiptables
コマンドを削除し、ip rule fwmark ..
コマンドをip rule uidrange ${real_uid}-${real_uid} lookup $real_uid
コマンドに置き換えます(それぞれのip rule del ..
コマンドについても同様です)。
Sudo
を介して実行されるコマンドの一部のサポートの別のバリアントは、UIDではなくユーザーのグループ(GID)に基づいてポリシールーティングを作成することです。これには追加の基本要件があります。
Sudo
追加のオプション(-g <user> -u root
またはsudoers
の同等の構成)を使用して実行し、元のGID番号を保持しますただし、そのようなSudo
の外部でユーザーが実行するUID 0プロセスを特定することはできません。
「UID 0プロセス」の問題に実際に対処するには、cgroupを使用できますが、当然、これにはさらに追加の要件があります。
iptables
コンパニオンルール。関連するトラフィックをiptables独自の「cgroup」モジュールでマークします。 Ubuntu 14.04Cgroupsを使用すると、net-class-idの設定は、pam_exec.so
によって実行される単純なスクリプトを介してかなりうまく処理される可能性があります
#!/bin/bash -e
uid=$(id -ru "${PAM_USER}")
mkdir -p /sys/fs/cgroup/net_cls/user/${uid} && echo $uid > /sys/fs/cgroup/net_cls/user/${uid}/net_cls.classid
echo $$ > /sys/fs/cgroup/net_cls/user/${uid}/cgroup.procs
次に、次の行を/etc/pam.d
の下の目的の構成ファイルに追加します。
session optional pam_exec.so /root/set-net-cls-id.sh
上記の行は、ssh
、コンソールログイン、デスクトップ環境などのインタラクティブサービスを介して開始されたすべてのセッションをカバーするために、従来の/etc/pam.d/common-session
ファイルに配置される可能性があります。
この設定では、ラッパースクリプトで使用されるiptables
コマンドは次のようになります。
iptables -t mangle -A OUTPUT -m cgroup --cgroup $real_uid -j MARK --set-mark $real_uid
-D
の代わりに-A
を使用したそれぞれの削除コマンド。
Cgroupソリューションの考えられるバリエーションは、systemd
への統合であり、systemd
の機能を使用して、pam_exec
を使用せずにcgroupを直接処理できます。
注ただし、このcgroupセットアップはUbuntu 14.04ではうまく機能しません。そのバージョンは、各ユーザーのセッションのcgroupを設定するために使用され、このソリューションによって設定されたセットアップを上書きするためです。むしろ、セッションごとにオンザフライで作成されたcgroupのclassid値を設定する必要があります。その名前は、cat /proc/self/cgroup
出力を解析することで簡単に取得できます。