オープンWi-Fiネットワークに接続すると、トラフィックを簡単に聞くことができることが知られています。 もちろん、現在ではますます多くのサイトがHTTPSを使用しています。 ただし、これはまだ100%にはほど遠い状態です。 このようなオープンWi-Fiネットワークに接続するとき、トラフィックを保護したいという自然な欲求があります。
この問題の一般的な解決策は、VPNを介した接続です。 この場合、トラフィックは暗号化された形式でVPNサーバーに送信され、そこからインターネットに送られます。
このソリューションには小さな欠点があります。VPN接続はまだ確立されていませんが、コンピューター上のすべてのアプリケーション(開いているブラウザータブを含む)は、VPN接続をバイパスしてインターネットにアクセスできます。
この記事では、これを回避する方法を説明します。
アイデア
この問題をどのように解決しますか?
一般的に、2つの例外を除き、すべてのアプリケーションへのすべてのネットワークアクセスをブロックします。
- VPNネットワークインターフェイスを介したアクセスを許可します。
- OpenVPNプロセスがインターネットに直接アクセスできるようにして、VPN接続を確立できるようにします。
これはiptablesで行います。
最初のポイントが非常に簡単に解決される場合、2番目のポイントは問題を提起します。 iptablesでは、プロセスの名前に一致するルールを作成できません。
すべてのプロセスについて、iptablesがVPNサーバーのハードコーディングされたIPへのアクセスを許可できます(このIPを介して他の接続が確立されていないことを前提としています)。 ホスト名を介してサーバーに接続することができないため、この解決策は不適切です。 さらに、キャプティブポータルに問題があります。 アクセスポイントで最初にWebページに移動し、そこで[同意する]をクリックする必要がある場合は、手動で例外を登録する必要があります。 したがって、このソリューションは理想とはほど遠いものです。
1つの解決策は、グループの使用に基づいています。 iptablesは、これらのパケットを送信したプロセスのGIDでパケットを照合できます。 このソリューションは非常にシンプルで効果的です。 しかし、あるプロセスが突然GIDを変更したい場合、すぐにインターネットにアクセスできなくなります。
2番目のオプションは、cgroupを使用することです。 特別なcgroupを作成して、インターネットへの無料アクセスを必要とするプロセスを配置できます。そのようなプロセスによって送信されるすべてのパケットには、iptablesで一致するラベルが付けられます。 このアプローチの利点は、プロセスグループを変更する必要がないことです。プロセスグループは他の目的に使用できます。 特定のcgroupをnet_clsサブシステムに割り当てることのみが必要です。 さらに、通常のグループのオプションとは異なり、プロセスを再起動することなく、あるcgroupから別のcgroupに「外出先で」転送できます。 この方法の短所:より複雑なセットアップ、最近リリースされたiptables v1.6.0が必要です(ほとんどのディストリビューションにはまだ追加されていません)。
通常のグループのオプションについて詳しく見ていきます。投稿の最後で、cgroupでこれをどのように行うかを簡単に説明します。
必要条件
OpenVPNベースのVPNがすでにあり、すべてのトラフィックを通過できると想定されています(たとえば、redirect-gateway def1オプションを使用)。
また、CONFIG_NETFILTER_XT_MATCH_OWNERとiptablesを備えたかなり新しいカーネルがあると仮定します。
iptablesのセットアップ
まず、特別なグループを作成する必要があります。 それをkillswitchと呼びます。
groupadd --system killswitch
次に、iptablesルールを追加します。
iptables -A OUTPUT -m owner --gid-owner killswitch -j ACCEPT iptables -A OUTPUT -o tun0 -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
ここで何が起こっていますか?
- GID killswitchを使用してプロセスによって送信されたパケットは、ネットワークに渡されます。
- tun0インターフェイス上のパケットは無条件でスキップされます。 これは、VPN接続の上に実装されているのと同じネットワークインターフェイスです。 このネットワークインターフェイスに別の名前がある場合(OpenVPN構成のdevオプションを使用すると、tunNではなく固定名を付けることができます)、上記のiptablesルールで変更します。
- loインターフェイス上のパケットは同じ方法でスキップされます。 loは、既知の127.0.0.1(localhost)が配置されているループバックインターフェイスです。 一部のアプリケーションはlocalhostを使用してプロセス間で通信するため、ブロックすることは望ましくありません。
- 他のすべてのパケットはブロックされます。 この場合、ICMPパケットの「管理上禁止」の送信でブロッキングが発生します(エラーコードは重要な役割を果たしません)。 この場合、プログラムはすぐにエラーを受け取り、タイムアウト前にハングしないため、これは単にパケットをドロップするよりも優れています。
すべてがうまくいけば、この時点でインターネットにアクセスできなくなっているはずです。
インターネットにアクセスできるプログラムを実行するには、sgユーティリティを使用できます(このグループにユーザーを追加する場合は、sudoを使用せずに呼び出すことができます)。 このグループがメイン(有効なGID)になるまで、プロセスはVPNなしではインターネットにアクセスできません。 iptablesは補足GIDをチェックしません!
sg killswitch 'ping ya.ru'
あとは、sgを使用して内部でOpenVPNクライアントを実行するだけです。
sg killswitch 'openvpn config.ovpn'
それだけです! この時点から、他のすべてのプログラムでインターネットを獲得しているはずです。
ボーナス:キャプティブポータル
インターネットにアクセスするには、最初にブラウザのページに移動して、たとえばモスクワの地下鉄のように「同意する」をクリックする必要がありますか?
この問題は簡単に解決できます。 OpenVPNクライアントが起動するように、他のアプリケーションを実行できます。
そのため、そのような場合には、永久プライベートモードの特別なFirefoxプロファイルがあります。 sg killswitchを介して実行すると、VPNなしでインターネットにアクセスすることもできます。
sg killswitch 'firefox -P my_special_profile_name -no-remote'
ボーナス:cgroups
cgroupsベースのソリューションには、iptables v1.6.0およびCONFIG_NETFILTER_XT_MATCH_CGROUPオプション付きのカーネルが必要です。
cgcreate -g net_cls:killswitch
次のコマンドを使用すると、Firefox VPNを使用せずにインターネットアクセスを発行してから、再度アクセスできます。
pgrep -w firefox | xargs cgclassify -g net_cls:killswitch pgrep -w firefox | xargs sudo cgclassify -g net_cls:/
ボーナス:xtables-addons条件
自宅または職場でVPNを介して座っている必要は特にありません。
-m condition --condition killswitch
最後のiptablesルールに追加されたxtables-
-m condition --condition killswitch
(REJECTを使用)は、
echo <0|1> > /proc/net/nf_condition/killswitch.
介してkillswitchを簡単に切り替え可能にし
echo <0|1> > /proc/net/nf_condition/killswitch.
おわりに
この記事では、iptablesを使用してkillswitchを実装するための2つのアプローチ、通常グループとcgroupを検討しました。 両方のオプションは非常に柔軟に機能し、必要に応じて、VPNなしで任意のプロセスがインターネットにアクセスできるようにします。 両方のアプローチはほぼ同等ですが、cgroupsを介した方法は設定が少し難しく、非常に新しいiptablesが必要ですが、プロセス中にアクセスを直接発行および撤回することができます。