単一プロセスの(発信)ネットワークアクセスをブロックすることは可能ですか?
Linux 2.6.24+(2.6.29まで実験的と見なされていました)では、そのためにネットワーク名前空間を使用できます。 unshare
ツールを使用して、カーネル(CONFIG_NET_NS=y
)とutil-linuxで 'ネットワーク名前空間'を有効にする必要があります。
次に、ネットワークにアクセスせずにプロセスを開始するのは、次のように簡単です。
unshare -n program ...
これにより、プロセスの空のネットワーク名前空間が作成されます。つまり、no loopbackを含むネットワークインターフェイスなしで実行されます。以下の例では、-rを追加して、現在の有効なユーザーIDとグループIDがスーパーユーザーIDにマップされた後でのみプログラムを実行します(Sudoは避けてください)。
$ unshare -r -n ping 127.0.0.1
connect: Network is unreachable
アプリにネットワークインターフェースが必要な場合は、新しいインターフェースを設定できます。
$ unshare -n -- sh -c 'ip link set dev lo up; ping 127.0.0.1'
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=32 time=0.066 ms
これにより、新しいlocalループバックが作成されることに注意してください。つまり、生成されたプロセスは、ホストの127.0.0.1
の開いているポートにアクセスできません。
名前空間内の元のネットワークにアクセスする必要がある場合は、 nsenter
を使用して他の名前空間を入力できます。
次の例では、PID 1によって使用されるネットワーク名前空間(-t 1
で指定)を使用してping
を実行します。
$ nsenter -n -t 1 -- ping -c4 example.com
PING example.com (93.184.216.119) 56(84) bytes of data.
64 bytes from 93.184.216.119: icmp_seq=1 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=2 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=3 ttl=50 time=134 ms
64 bytes from 93.184.216.119: icmp_seq=4 ttl=50 time=139 ms
--- example.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 134.621/136.028/139.848/2.252 ms
Linuxには ネットワーク名前空間 と呼ばれる機能があり、基本的に同じマシン上に複数のネットワークスタックを設定し、実行時に1つをプログラムに割り当てることができます。これは通常コンテナに使用される機能ですが、目的に応じて使用することもできます。
ip netns
サブコマンドがそれを管理します。何にもアクセスできない新しいネットワーク名前空間の作成は簡単です。これは、新しい名前空間のデフォルトの状態です。
root@Host:~# ip netns add jail
これで、その名前空間に切り替えると、かなり簡単に構成できます。あなたはおそらくそれを育てたいと思うでしょう、そしてそれだけです:
root@Host:~# ip netns exec jail /bin/bash
root@Host:~# ip addr add 127.0.0.1/8 dev lo
root@Host:~# ip link set dev lo up
root@Host:~# exit
ネットワークなしでコマンドを実行したい場合は、その刑務所で実行するだけです。
root@Host:~# ip netns exec jail su user -c 'ping 8.8.8.8'
connect: Network is unreachable
必要に応じて、ネットワークに到達できません。 (別のネットワークスタックにはiptables
ルールなどが含まれているため、あらゆる種類の興味深いことができます。)
Iptablesを使用して、そのプロセスをcgroupに移動できます。
mkdir /sys/fs/cgroup/net_cls/block
echo 42 > /sys/fs/cgroup/net_cls/block/net_cls.classid
iptables -A OUTPUT -m cgroup --cgroup 42 -j DROP
echo [pid] > /sys/fs/cgroup/net_cls/block/tasks
はい、カスタマイズされたapparmorプロファイル、つまり
/usr/bin/curl {
...
# block ipv4 acces
deny network inet,
# ipv6
deny network inet6,
# raw socket
deny network raw,
}
ただし、そのようにすると、アクセスを許可するファイルのリストも生成する必要があり、手順全体が少し複雑になる可能性があります。そして こちらのヘルプドキュメントを参照
firejail sandbox を使用できます(seccomp機能を備えたカーネルで動作するはずです)。
使うには
firejail --noprofile --net=none <path to executable>
--noprofile
はデフォルトのサンドボックスを無効にします--net=none
はネットワークを無効にします
ほとんどのディストリビューションはすでにパッケージを提供していると思いますが、Firejailが提供されていなくても、ビルドツールチェーンと名前空間/ seccomp対応カーネル以外の依存関係は事実上ありません。
ネットワーキングに関してfirejail --help
で示すことができるfirejailのその他のいくつかの素敵な機能(ループバックインターフェイスの提供やip/dnsのブロックなど)がありますが、これでうまくいくはずです。また、それはdoesn't require root
です。
Iptablesだけではできません。この機能 一時的に存在した ですが、確実に機能させることができず、放棄されました。
プロセスを専用ユーザーIDとして実行できる場合、iptablesはowner
モジュールを使用して実行できます。
iptables -A OUTPUT -m owner --uid-owner 1234 -j DROP
Iptables:conntrackと所有者との送信トラフィックのマッチング。奇妙なドロップで機能します の例を参照してください。 iptables/pfルールはXYアプリケーション/ユーザーのみを許可しますか?
独自のコンテナーでプロセスを実行できる場合は、そのコンテナーを個別にファイアウォールで保護できます(ネットワークから完全に切断されていても)。
セキュリティモジュールは、ネットワーク機能へのプロセスのアクセスをフィルタリングできます。 warl0ckの答え はAppArmorの例を示します。
ソリューション1:ファイアウォール:
Douane または Opensnitch のようなファイアウォールを使用できますが、これらのアプリケーションは100%効率的ではないか、開発の初期段階にあります(2019年の時点で多くのバグなどがあります)。
ソリューション2:カーネルMAC:
カーネルMACは、最もよく知られているファイアウォールとして使用できます Tomoyo 、 Selinux および Apparmor このソリューションは、安定性と効率に関しては最良のソリューションです(ファイアウォールソリューション)しかし、ほとんどの場合、これを設定することはどういうわけか複雑です。
ソリューション3:Firejail:
Firejail は、アプリケーションのネットワークアクセスをブロックするために使用できます。これはrootを必要としません
firejail --noprofile --net=none command-application
ソリューション4:共有解除
Unshareは、ネットワークがなくても別の名前空間でアプリケーションを起動できますが、これにはルートFireJailのソリューションがほぼ同じである必要がありますが、ルートは必要ありません
unshare -r -n application-comand
ソリューション5:Proxify:
1つの解決策は、アプリケーションをnull/fakeプロキシにプロキシ化することです。 tsocks または proxybound を使用できます。ここにいくつかあります セットアップの詳細
ソリューション6:Iptables:
他の簡単な解決策はiptablesで、アプリケーションをブロックするように設定できます
groupadd no-internet
grep no-internet /etc/group
useradd -g no-internet username
usermod -a -G no-internet userName
確認する : Sudo groups userName
nano /home/username/.local/bin/no-internet
chmod 755 /home/username/.local/bin/no-internet
#!/bin/bash
sg no-internet "$@"
iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP
4.たとえば、Firefoxで次のコマンドを実行して確認します。
no-internet "firefox"
5.例外を設定し、プログラムにローカルネットワークへのアクセスを許可する場合:
iptables -A OUTPUT -m owner --gid-owner no-internet -d 192.168.1.0/24 -j ACCEPT
iptables -A OUTPUT -m owner --gid-owner no-internet -d 127.0.0.0/8 -j ACCEPT
iptables -A OUTPUT -m owner --gid-owner no-internet -j DROP
6.永続化する
起動時にiptablesルールを適用する1つの方法は、systemdでサービスとしてルールを追加することです
cat /usr/lib/systemd/system/nonet.service
[Unit]
Description=Nonet group iptable update
After=network.target
After=xsession.target
After=iptables.service
After=shorewall.service
[Service]
Type=oneshot
RemainAfterExit=true
StandardOutput=journal
ExecStart=/bin/bash /home/user/Scripts/Nonet.iptables.sh
使用しているディストリビューションによって異なりますが、それは通常OSのMACシステムに含まれている機能です。前述のように、UbuntuまたはSuSEのAppArmorはこれを行うことができます。 RHELを使用している場合は、実行中のプロセスのラベルに基づいて、特定のポート番号へのアクセスを許可または拒否するようにSELinuxを構成できます。 これ は、高速グーグルの後で見つけることができるすべてですが、もっとよく見て、それがあなたに一般的なアイデアを与えるなら、オンラインのより深いリソースがおそらくあるでしょう。
seccomp-bpf を使用して、一部のシステムコールをブロックできます。たとえば、プロセスがソケットFDを作成しないようにするために socket
システムコールをブロックすることができます。
Libseccompを使用して動作するsocket
システムコールを妨げるこのapprocahの example を書きました。概要は(エラーチェックなし)です。
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
seccomp_Arch_add(ctx, SCMP_Arch_NATIVE);
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(socket), 1, SCMP_CMP(0, SCMP_CMP_EQ, pf));
seccomp_load(ctx);
execvp(argv[1], argv+1);
これにはroot権限は必要ありません。
完全なサンドボックスははるかに複雑ですが、非協力的/悪意のあるプログラムをブロックするためにこれを無秩序に使用しないでください。
Systemd v235以降、別の非常に簡単なオプションもあります:
systemdを使用したIPアカウンティングとアクセスリスト
TL; DR:systemdは、サービスごとのIPトラフィックアカウンティング、およびIPアドレス範囲のアクセス制御を実行できるようになりました。