Memblokir akses jaringan dari suatu proses?

74

Apakah mungkin untuk memblokir akses jaringan (keluar) dari satu proses?

Larkee
sumber
6
Bagaimana Anda bermaksud mengidentifikasi prosesnya? PID, nama, jalur?
Marco
1
Akses apa yang ingin Anda blokir? Beberapa program menggunakan akses jaringan melalui localhost(ke mesin yang sama) untuk melakukan pekerjaan mereka.
vonbrand
Lihat juga LD_PRELOAD atau yang serupa untuk mencegah akses jaringan , jika prosesnya bekerja sama.
Gilles 'SO- stop being evil'

Jawaban:

78

Dengan Linux 2.6.24+ (dianggap eksperimental hingga 2.6.29), Anda dapat menggunakan ruang nama jaringan untuk itu. Anda perlu mengaktifkan 'namespace jaringan' di kernel ( CONFIG_NET_NS=y) dan util-linux dengan unsharealat ini.

Kemudian, memulai proses tanpa akses jaringan sesederhana:

unshare -n program ...

Ini menciptakan ruang nama jaringan kosong untuk proses. Artinya, dijalankan tanpa antarmuka jaringan, termasuk tanpa loopback . Dalam contoh di bawah ini kami menambahkan -r untuk menjalankan program hanya setelah ID pengguna dan grup yang efektif saat ini telah dipetakan ke yang superuser (hindari sudo):

$ unshare -r -n ping 127.0.0.1
connect: Network is unreachable

Jika aplikasi Anda membutuhkan antarmuka jaringan, Anda dapat mengatur yang baru:

$ 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

Perhatikan bahwa ini akan membuat loopback lokal baru . Artinya, proses spawned tidak akan dapat mengakses port terbuka host 127.0.0.1.


Jika Anda perlu mendapatkan akses ke jaringan asli di dalam namespace, Anda dapat menggunakan nsenteruntuk memasukkan namespace lainnya.

Contoh berikut berjalan pingdengan namespace jaringan yang digunakan oleh PID 1 (ditentukan melalui -t 1):

$ 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
Michał Górny
sumber
4
unshare -ntampaknya membuang "Operasi tidak diizinkan" tanpa roothak istimewa, apa pun yang saya lewatkan tentang hal itu?
botak
1
Mungkin pertanyaan bodoh ... apakah namespace ini juga berlaku untuk proses anak / proses yang disebut aplikasi yang tidak digunakan bersama?
bonanza
3
Iya. Ini diwarisi oleh semua anak yang lahir setelah mengganti namespace.
Michał Górny
2
Saya terlihat seperti program apa pun yang ingin saya batalkan mis. Dengan sudo unshare -nmewarisi hak root. Karena saya memerlukan sudo untuk menelepon unshare, saya bertanya-tanya bagaimana saya bisa memastikan bahwa program yang dipanggil tidak memiliki hak root.
bonanza
3
Satu liner untuk membatasi proses ke pengguna. Cukup sudo dua kali: sudo unshare -n sudo -u dude bash -c 'echo Hello, my name is $USER'@ThorSummoner bbs.archlinux.org/viewtopic.php?id=205240
Jakub Bochenski
21

Linux memiliki fitur yang disebut ruang nama jaringan yang memungkinkan Anda untuk secara esensial memiliki beberapa tumpukan jaringan pada mesin yang sama, dan menetapkan satu untuk suatu program saat menjalankannya. Ini adalah fitur yang biasanya digunakan untuk wadah, tetapi Anda juga dapat menggunakannya untuk mencapai apa yang Anda inginkan.

ip netnsSub - perintah mengelolanya. Membuat namespace jaringan baru tanpa akses apa pun itu mudah, itu adalah status default namespace baru:

root@host:~# ip netns add jail

Sekarang, jika Anda beralih ke namespace itu, Anda dapat mengonfigurasinya dengan cukup mudah. Anda mungkin ingin memunculkan lo di dalamnya, dan hanya itu:

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

Sekarang ketika Anda ingin menjalankan perintah Anda tanpa jaringan, Anda jalankan saja di penjara itu:

root@host:~# ip netns exec jail su user -c 'ping  8.8.8.8'
connect: Network is unreachable

Jaringan, seperti yang diinginkan, tidak dapat dijangkau. (Anda dapat melakukan semua jenis hal menarik sebagai tumpukan jaringan terpisah termasuk iptablesaturan, dll.)

derobert
sumber
Meskipun saya perlu sudo ipmengeksekusi perintah ip, begitu saya menjadi bash, saya hanya mengeksekusi su someuseruntuk mendapatkan shell unprivileged untuk pengguna 'pengguna'.
bijak
11

Anda bisa menggunakan iptables dan memindahkan proses itu ke dalam 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
Jan Mueller
sumber
1
bagaimana menghapus pid dari file tugas itu memberikan kesalahan ketika saya mencoba untuk menghapus atau menghapus data dari file itu meskipun saya dengan pengguna root
pkm
@ pkm untuk mengaktifkan jaringan kembali, Anda hanya perlu mengulang [pid] ke /sys/fs/cgroup/net_cls/tasks(tidak ada 'blok' di jalur)
Duka
10

Ya, dengan profil apparmor yang disesuaikan, yaitu

/usr/bin/curl {
    ...

    # block ipv4 acces
    deny network inet,
    # ipv6 
    deny network inet6,
    # raw socket
    deny network raw,

}

Tetapi dengan cara itu, Anda perlu membuat daftar file yang diizinkan untuk diakses juga, seluruh prosedur bisa sedikit rumit. Dan lihat dokumen bantuan di sini

bunga aster
sumber
7

Anda dapat menggunakan kotak pasir firejail (harus bekerja pada kernel dengan fitur seccomp).

Untuk menggunakannya lakukan saja

firejail --noprofile --net=none <path to executable>

--noprofilemenonaktifkan sandbox default --net=nonemenonaktifkan jaringan

Saya percaya bahwa sebagian besar distro sudah menyediakan paket tetapi bahkan jika mereka tidak firjail sebenarnya tidak memiliki dependensi selain membangun toolchain dan namespace / seccomp enabled kernel.

Ada beberapa fitur bagus lain dari firejail yang dapat ditunjukkan firejail --helpsehubungan dengan jaringan (seperti hanya menyediakan antarmuka loopback atau memblokir ip / dns dll) tetapi ini harus melakukan pekerjaan. Itu juga doesn't require root.

pruzinat
sumber
5

Anda tidak dapat melakukannya dengan iptables saja. Fitur ini secara singkat ada , tetapi tidak dapat dibuat untuk bekerja dengan andal dan ditinggalkan.

Jika Anda dapat menjalankan proses sebagai ID pengguna khusus, iptables dapat melakukannya dengan ownermodul:

iptables -A OUTPUT -m owner --uid-owner 1234 -j DROP

Lihat contoh di Iptables: mencocokkan lalu lintas keluar dengan conntrack dan pemilik. Bekerja dengan tetes aneh , aturan iptables / pf hanya mengizinkan aplikasi / pengguna XY?

Jika Anda dapat menjalankan proses dalam wadahnya sendiri, Anda dapat membuat firewall wadah itu secara mandiri (bahkan membuatnya benar-benar terputus dari jaringan).

Modul keamanan dapat memfilter akses proses ke fitur jaringan. Jawaban warl0ck memberi contoh dengan AppArmor.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Solusi 1: Firewall:

Kita dapat menggunakan firewall seperti Douane atau Opensnitch TAPI aplikasi tersebut tidak 100% efisien atau dalam tahap awal pengembangan (memiliki banyak bug, dll. Hingga 2019)

Solusi 2: Kernel MAC:

Kernel Mac dapat digunakan sebagai firewall yang paling dikenal adalah Tomoyo , SELinux dan AppArmor Solusi ini adalah yang terbaik ketika datang ke stabilitas dan efisiensi (solusi firewall) tetapi sebagian besar waktu pengaturan ini entah bagaimana rumit.

Solusi 3: Firejail:

Firejail dapat digunakan untuk memblokir akses jaringan untuk suatu aplikasi yang tidak memerlukan root apa pun yang bisa diuntungkan oleh pengguna

firejail --noprofile --net=none command-application

Solusi 4: Batalkan Berbagi

Unshare dapat memulai aplikasi pada namespace yang berbeda tanpa jaringan tetapi ini membutuhkan solusi root firejail melakukan hal yang persis sama tetapi tidak memerlukan root

unshare -r -n application-comand

Solusi 5: Proksi:

Salah satu solusinya adalah proksi aplikasi ke proxy nol / palsu . Kita bisa menggunakan tsocks atau proxybound . Berikut ini beberapa detail tentang pengaturan

Solusi 6: Iptables:

Solusi mudah lainnya adalah iptables, bisa jadi pengaturan untuk memblokir aplikasi

  1. Buat, validasikan grup baru ; tambahkan pengguna yang diperlukan ke grup ini:
    • Membuat: groupadd no-internet
    • Mengesahkan: grep no-internet /etc/group
    • Tambahkan pengguna: useradd -g no-internet username

      Catatan: Jika Anda memodifikasi pengguna yang sudah ada, Anda harus menjalankan: usermod -a -G no-internet userName tanyakan:sudo groups userName

  2. Buat skrip di jalur Anda dan buat agar bisa dieksekusi:
    • Membuat: nano /home/username/.local/bin/no-internet
    • Dapat dieksekusi: chmod 755 /home/username/.local/bin/no-internet
    • Konten: #!/bin/bash
                    sg no-internet "$@"

  3. Tambahkan aturan iptables untuk menjatuhkan aktivitas jaringan untuk grup tanpa internet :
    • iptables -I OUTPUT 1 -m owner --gid-owner no-internet -j DROP

      Catatan: Jangan lupa untuk membuat perubahan permanen, jadi itu akan diterapkan secara otomatis setelah reboot . Melakukannya, tergantung pada distribusi Linux Anda.


   4. Periksa, misalnya di Firefox dengan menjalankan:

  • no-internet "firefox"

   5. Jika Anda ingin membuat pengecualian dan mengizinkan suatu program untuk mengakses jaringan lokal :

  • 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. Jadikan permanen

   Salah satu cara untuk menerapkan aturan iptables saat boot adalah dengan menambahkan aturan sebagai layanan dengan 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
intika
sumber
1
Ini adalah panduan yang sangat bagus. Terima kasih. Meskipun, bagi saya, perintah no-internet saya sepertinya tidak pernah melewati parameter, jadi saya gunakan sg no-internetuntuk saat ini.
Zach Bloomquist
@Zach saya memperbarui jawaban saya, Anda mungkin tertarik pada firejail;)
intika
2

Tergantung pada apa distro yang Anda gunakan, tetapi itu adalah fitur yang biasanya termasuk dalam sistem MAC OS. Seperti yang dinyatakan sebelumnya, Ubuntu atau AppArmor SuSE dapat melakukan ini. Jika Anda menggunakan RHEL, Anda dapat mengonfigurasi SELinux untuk mengizinkan atau menolak akses ke nomor port tertentu berdasarkan label proses eksekusi. Ini semua bisa saya temukan setelah beberapa googling cepat tetapi mungkin ada lebih banyak sumber daya online jika Anda melihat lebih keras dan itu memberi Anda ide umum.

Bratchley
sumber
2

Anda dapat menggunakan seccomp-bpf untuk memblokir beberapa panggilan sistem. Misalnya mungkin ingin memblokirsocket panggilan sistem untuk mencegah proses membuat soket FD.

Saya menulis contoh persetujuan ini yang mencegah socketpanggilan sistem untuk bekerja menggunakan libseccomp. Ringkasannya adalah (tanpa memeriksa kesalahan):

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);

Ini tidak membutuhkan hak root.

Namun, kotak pasir lengkap jauh lebih kompleks sehingga Anda tidak boleh menggunakan perintah ini untuk memblokir program yang tidak kooperatif / jahat.

ysdx
sumber
Bisakah Anda memberi contoh cara menggunakan ini? Apakah ini membutuhkan hak akses root untuk bekerja?
bonanza
-4

Anda bisa menggunakan program baris perintah yang disebut "proxychains" dan coba salah satu dari kemungkinan berikut:

Setel yang digunakannya ...

  • ... proxy yang tidak ada? (Saya tidak tahu apakah itu akan menjalankannya dengan proksi "tidak valid")
  • ... proxy lokal (seperti "tinyproxy", "squid", "privoxy", ...) yang membatasi akses ke internet? (Cukup gunakan ACL)

Saya belum mengujinya sendiri jadi saya tidak tahu apakah itu berfungsi ...

drkhsh
sumber
Mem-posting solusi yang belum diuji umumnya bukan ide yang baik.
Twirrim
proxychains dengan proxy yang tidak ada (seperti localhost: 1234 atau sejenisnya) mungkin sebenarnya merupakan pendekatan yang solid, namun
phil294