
特定のWi-Fiアクセスポイントに接続しているときに特定のアプリケーションがインターネットにアクセスできないようにするソリューションを探しています。私の具体的なユースケースは、携帯電話テザリングを介して接続されている場合は、Dropbox、Spotifyなどのアプリが私のすべてのデータを使用できないようにすることです。
ソリューションはネットワーク自体の外側の他のレベルにある可能性がありますが、「アプリケーションの終了」ソリューションは避けることをお勧めします。
私はArchlinuxを使用していますが、他のディストリビューションに良い解決策がある場合は、間違いなく良い方向性を提供できます。
答え1
質問は2つの部分に分けることができます。
制限されたアクセスポイント(テザリング)を使用するときの識別
制限されたアプリケーションに属する発信パケットの識別
2つを組み合わせると、制限されたアクセスポイントを使用して発行された制限付きアプリケーションに属するパケットが識別されます(そのようなパケットは破棄される可能性があります)。
準備する
説明の後ろではなく前に貼り付けるので、すべての内容を順番に入力することをお勧めします。
2つのiptablesチェーンを使用してください。 1つは仕事をします(特定のアプリをブロック)、別(テザーの有効化)簡単に更新できます。
iptables -N tetheractivated
iptables -N blocksomeapps
iptables -I OUTPUT -j tetheractivated
1. アクセスポイント
この回答は次のように仮定します。一つアクセスポイントはいつでも使用されており、既知のネットワークインターフェイス名(wlan0
)を使用しています。また、wpa_supplicant
低レベルのデーモンによって処理されると仮定します。クエリできる限り、スタンドアロンであるかNetworkManagerのバックエンドであるかは重要ではありません。wpa_cli
そしてその-a
(操作)オプション。
アクションスクリプトmyaction.sh
:
#!/bin/sh
TETHERSSID='My Tethering'
case "$2" in
'CONNECTED')
ssid="$(wpa_cli -p "$WPA_CTRL_DIR" -i "$1" get_network "$WPA_ID" ssid)"
# Note: ssid's value already comes with an added pair of double quotes around:
# adding one as well
if [ "$ssid" = \""$TETHERSSID"\" ]; then
iptables -A tetheractivated -j blocksomeapps
fi
;;
'DISCONNECTED')
iptables -F tetheractivated
;;
esac
その後、プログラムを実行し続け、このスクリプト(実行可能でなければならない)をイベントループとして使用します。
wpa_cli -a myaction.sh
これにより、iptablesチェーンが作成されます。特定のアプリをブロック宛先SSIDに接続するとパケットパスに表示され、接続が切断されると(SSIDから)パケットパスから削除されます。
2. 適用制限
これは扱いにくいです。特定のプロセスに属するパケットを識別する方法はいくつかあり、いずれにしても追加の準備が必要です。いくつかの方法は他の方法よりも多くを必要とします。
いくつかの例:
- 追加のチェックのために、パケットをユーザースペースアプリケーションのキューに入れることができます(プログラムはCまたはPythonで作成する必要があります)。
- 制限されたプロセスは別のユーザーとして実行でき、処理が非常に簡単です。
- 制限されたプロセスは、独自のプライベートネットワーク名前空間で実行できます。完了したら処理が簡単です。まず、設定とルートアクセスを含めてユーザーアクセスを返して実行すると、問題が発生する可能性があります。
このQ&Aで見つけることができる非常に簡単な方法は次のとおりです。プロセスへのネットワークアクセスをブロックしますか?
同じペアネットワークCLSグループiptablesで照会できる値があります(メインターゲット:Traffic Controllerに加えてtc
)。
特定の生成ネットワークCLSグループ化し、特定の分類IDを指定します。
# mkdir -p /sys/fs/cgroup/net_cls/blocksomeapps
# echo 42 > /sys/fs/cgroup/net_cls/blocksomeapps/net_cls.classid
ターゲットプロセス(スレッドを含める必要があります)を識別し、それをグループに追加します(tasks
一度に1つのpid(またはtid)を作成する)。プロセスが大幅に変更されると危険になる可能性があるため、アプリケーションの起動中に実行するのが最善です。もちろん、一度完了すると、子供たちは自動的に同じグループに残ります。
Firefoxを例にしましょう(複数のプロセスで複数のスレッドを使用するので、pgrep
すべてのスレッドIDを出力する必要があります--lightweight
):
# for i in $(pgrep --lightweight -f firefox); do echo $i > /sys/fs/cgroup/net_cls/blocksomeapps/tasks; done
(グループから削除するpid / tidは親グループに記録する必要があります/sys/fs/cgroup/net_cls/tasks
)
空のリンクブロックルールを追加特定のアプリをブロック以前に準備したもの:
# iptables -A blocksomeapps -m cgroup --cgroup 42 -j DROP
転送されるパケットのみをブロックするには、wlan0
次の代わりに使用してください。
# iptables -A blocksomeapps -o wlan0 -m cgroup --cgroup 42 -j DROP
ただし、DNSキャッシュデーモン自体がブロックされていないため、これらのアプリケーションによって生成された間接的なアクティビティ(ローカルDNSキャッシュデーモンへのDNSクエリなど)は依然として一部のデータトラフィックを生成する可能性があります。
メモ:
- SSID部分は、どこかでルーティング検証を実行し、複数の同時アクセスポイントを処理することによって改善できますが、非常に迅速に複雑になります。単純な
myaction.sh
スクリプトだけでは十分ではありません(接続のSSIDを知ることは、まだ構成されていないネットワーク層に関する情報を提供していないためです)。 - 今、cgroupsystemdまたはcgmanagerを介してインストールおよび構成されている可能性があります。利用できない場合、設定はこのQ&Aの範囲外です。
- cgroupv1がゆっくりと交換されています。cgroupv2なので、この回答はいつかv2に適用する必要があります。
- さらに、このアプローチは、それを使用して作成されたコンテナまたはネットワーク名前空間と互換性がないか、少なくとも使用するのが難しい場合があります。
ip netns
どちらもcgroupの使用に制限があるためです(たとえばip netns
、再ip netns exec ...
マウントするとツリーが使用できなくなり、実際には使用できなくなります)。 。 2回インストール)。/sys/
/sys/fs/cgroup
- すべての出力パケットが通過するグループマッチ。負荷を軽減するために
tetheractivated
一般的なStatefulルールの後に挿入することができますが、すでにESTABLISHED
設定されているフローは削除されないため、アプリケーションに応じてしばらく動作できます。これが役に立つかもしれませんconntrack
(-D
または-F
)。 - 交通を防ぐよりiptables(またはnftables)
tc
(そしてグループフィルタ)を使用して、厳しい帯域幅制限を適用できます。発信トラフィックが完全に制御されている間、着信トラフィックの場合も同様です。パケットが受信されると(そして前の発信トラフィックと同じフローに関連付けられている)、破棄されてもデータは消費されます。
答え2
2つの状況があります。
ケース1
特定のアプリケーションへのアクセスのみ拒否したい場合
ここで iptables エントリを使用できます。アプリケーションがどのプロトコル(TCP / UDP)を使用しているかを知る必要があります。これにより、次のように予防できます。
sudo iptables -A OUTPUT -p tcp --dport 80 -j DROP
これにより、すべてのアプリケーションがTCPポート80にアクセスするのを防ぎます。残念ながら、アプリケーションに独自のプロトコルがなく、HTTPなどのプロトコルを使用している場合、この方法は機能しません。これにより、合法的なトラフィックもブロックされます。
ケース2
特定のアプリだけがインターネットにアクセスできるようにするには、以下をホワイトリストに追加します。
sudo iptables -A OUTPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -P OUTPUT DROP
これにより、TCPポート80にのみアクセスが許可されます。もちろん、ポート80ルールなど、より多くのルールを追加できます。ただし、他のすべての発信パケット(ループバックトラフィックを除く)はブロックされます。
この構成は、再起動後も維持されません。この問題を解決するには、iptables-persistを試してみてください。さらに、これはIPv6トラフィックをブロックしないため、同じコマンドを入力する必要がありますが、IPv6をフィルタリングするにはiptablesをip6tablesに置き換える必要があります。