iptables - Target untuk merutekan paket ke antarmuka tertentu?

25

Server rumah saya memiliki dua antarmuka utama, eth1(koneksi internet standar) dan tun0(terowongan OpenVPN). Saya ingin menggunakan iptablesuntuk memaksa semua paket yang dihasilkan oleh proses lokal yang dimiliki oleh UID 1002 untuk keluar tun0, dan semua paket lain untuk keluar eth1.

Saya dapat dengan mudah menandai paket yang cocok:

iptables -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11

Sekarang, saya ingin meletakkan beberapa aturan dalam rantai POSTROUTING (mungkin dari tabel mangle) untuk mencocokkan paket yang ditandai dengan 11 dan mengirimkannya ke tun0, diikuti oleh aturan yang cocok dengan semua paket dan mengirimkannya ke eth1.

Saya menemukan target ROUTE, tetapi sepertinya hanya menulis ulang antarmuka sumber (kecuali saya membacanya dengan salah).

Apakah iptables mampu melakukan ini? Apakah saya harus main-main dengan tabel routing (via ip routeatau hanya routeperintah legacy ) saja?

Sunting: Saya pikir mungkin saya harus memberikan informasi lebih lanjut. Saya tidak memiliki aturan iptables lain saat ini (walaupun saya dapat membuat beberapa aturan untuk melakukan tugas yang tidak terkait di masa depan). Juga, output dari ip routeadalah:

default via 192.168.1.254 dev eth1  metric 203
10.32.0.49 dev tun0  proto kernel  scope link  src 10.32.0.50
85.17.27.71 via 192.168.1.254 dev eth1
192.168.1.0/24 dev eth1  proto kernel  scope link  src 192.168.1.73  metric 203

Saya belum menyentuh tabel routing - ini hanya bagaimana saat ini (walaupun terlihat cukup kotor). Maaf, tetapi saya tidak memiliki routeperintah warisan yang diinstal pada mesin ini.

Dan output dari ip addr(tentu saja, eth0 dan eth2 dapat diabaikan - mereka adalah NIC yang tidak digunakan saat ini):

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 1c:6f:65:2a:73:3f brd ff:ff:ff:ff:ff:ff
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast     state UP qlen 1000
    link/ether 00:1b:21:9d:4e:bb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.73/24 brd 192.168.1.255 scope global eth1
    inet6 fe80::21b:21ff:fe9d:4ebb/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether 00:1b:21:6a:c0:4b brd ff:ff:ff:ff:ff:ff
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc     pfifo_fast state UNKNOWN qlen 100
    link/none
    inet 10.32.0.50 peer 10.32.0.49/32 scope global tun0

Sunting: Saya mendapatkan sesuatu yang berfungsi, tetapi tidak meneruskan paket yang ditandai ke tun0. Pada dasarnya, saya menambahkan tabel (11), dan menggunakan:

ip route add table 11 via 10.32.0.49 dev tun0
ip rule add priority 10000 fwmark 11 table 11

Ketika saya baru saja sudo -u user1000 wget -qO- whatismyip.org, saya mendapatkan alamat IP eksternal rumah saya, tetapi jika saya melakukannya sudo -u user1002 wget -qO- whatismyip.org, saya juga mendapatkan alamat IP rumah saya (tetapi saya harus mendapatkan IP di ujung lain terowongan OpenVPN).

Menjalankan iptables -vLmengonfirmasi bahwa paket-paket tersebut dicocokkan dengan aturan penandaan, tetapi mereka tampaknya tidak mengikuti aturan perutean.

EDIT: Saya sudah menghabiskan waktu yang lama untuk ini, dan meskipun masih tidak berhasil, saya pikir saya sedikit lebih dekat.

Aturan iptables harus dalam manglerantai OUTPUT tabel. Saya pikir saya juga membutuhkan aturan MASQUERADE di natrantai POSTROUTING tabel, untuk mengatur alamat sumber. Namun, perutean ulang yang terjadi setelah kicau OUTPUT tidak berfungsi dengan benar.

Saya telah menghabiskan 5 jam untuk hal ini sekarang, jadi saya beristirahat dan mungkin akan kembali lagi nanti malam atau besok.

Ethan
sumber

Jawaban:

26

Saya baru-baru ini mengalami masalah yang sama, meskipun sedikit berbeda. Saya ingin merutekan hanya port TCP 25 (SMTP) melalui antarmuka OpenVPN tap0, sementara merutekan semua lalu lintas lainnya (bahkan untuk host yang sama) melalui antarmuka default.

Untuk melakukannya, saya harus menandai paket dan mengatur aturan untuk menanganinya. Pertama, tambahkan aturan yang membuat paket rute kernel ditandai dengan 2melalui tabel 3(dijelaskan nanti):

ip rule add fwmark 2 table 3

Anda bisa menambahkan nama simbolis ke /etc/iproute2/rt_tables, tetapi saya tidak repot-repot melakukannya. Jumlah 2dan 3dipilih secara acak. Sebenarnya, ini bisa sama tetapi untuk kejelasan saya tidak melakukannya dalam contoh ini (walaupun saya melakukannya di pengaturan saya sendiri).

Tambahkan rute untuk mengarahkan lalu lintas melalui antarmuka yang berbeda, dengan asumsi gateway adalah 10.0.0.1:

ip route add default via 10.0.0.1 table 3

Sangat penting! Bilas cache routing Anda, jika tidak, Anda tidak akan mendapatkan respons kembali dan duduk dengan rambut Anda selama beberapa jam:

ip route flush cache

Sekarang, tetapkan aturan firewall untuk menandai paket yang ditunjuk:

iptables -t mangle -A OUTPUT -p tcp --dport 465 -j MARK --set-mark 2

Aturan di atas hanya berlaku jika paket berasal dari mesin lokal. Lihat http://inai.de/images/nf-packet-flow.png . Sesuaikan dengan kebutuhan Anda. Misalnya, jika Anda hanya ingin merutekan lalu lintas HTTP keluar melalui tap0antarmuka, ubah 465 menjadi 80.

Untuk mencegah paket yang dikirim untuk tap0mendapatkan alamat LAN Anda sebagai IP sumber, gunakan aturan berikut untuk mengubahnya ke alamat antarmuka Anda (dengan asumsi 10.0.0.2sebagai alamat IP untuk antarmuka tap0):

iptables -t nat -A POSTROUTING -o tap0 -j SNAT --to-source 10.0.0.2

Terakhir, relakskan validasi sumber jalur sebaliknya. Beberapa menyarankan Anda untuk mengaturnya 0, tetapi 2tampaknya pilihan yang lebih baik sesuai dengan https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt . Jika Anda melewati ini, Anda akan menerima paket (ini dapat dikonfirmasi menggunakan tcpdump -i tap0 -n), tetapi paket tidak diterima. Perintah untuk mengubah pengaturan agar paket diterima:

sysctl -w net.ipv4.conf.tap0.rp_filter=2
Lekensteyn
sumber
Mengapa Anda menggunakan SNAT, bukan MASQUERADE? Bukankah MASQUERADE melakukan hal yang sama, kecuali alamat IP dikumpulkan dari antarmuka saat "runtime" dan tidak di-hardcode ke file konfigurasi?
Ethan
6
@Ethan From man iptables: Ini hanya dapat digunakan dengan koneksi IP (dialup) yang ditetapkan secara dinamis: jika Anda memiliki alamat IP statis, Anda harus menggunakan target SNAT. Masquerading setara dengan menentukan pemetaan ke alamat IP dari antarmuka paket keluar, tetapi juga memiliki efek koneksi yang dilupakan ketika antarmuka turun. Anda benar, tetapi karena IP saya tidak akan pernah berubah, saya memutuskan untuk menggunakan SNAT per rekomendasi oleh halaman manual.
Lekensteyn
Saya pikir (walaupun tidak diuji) langkah terakhir (validasi sumber jalur balik) tidak diperlukan. Anda bisa menambahkan aturan lain ke PREROUTINGrantai ke DNATalamat sumber yang benar (sesuai dengan gateway default Anda).
Christian Wolf
7

Saya memecahkan ini. Masalah ini dengan aturan routing table 11. Tabel 11 adalah mendapatkan hit, tetapi aturan routing yang membuatnya bisa dioperasi. Script ini adalah apa yang saya gunakan sekarang, dan tampaknya berfungsi dengan baik (meskipun jelas khusus untuk setup saya). Juga, saya membuat tabel baru 21 yang ditujukan untuk uplink utama (eth1).

# Add relevant iptables entries.
iptables -t mangle -A OUTPUT -m owner --uid-owner 1002 -j MARK --set-mark 11
iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

# Flush ALL THE THINGS.
ip route flush table main
ip route flush table 11
ip route flush table 21
ip rule flush

# Restore the basic rules and add our own.
ip rule add lookup default priority 32767
ip rule add lookup main priority 32766
ip rule add fwmark 11 priority 1000 table 11
# This next rule basically sends all other traffic down eth1.
ip rule add priority 2000 table 21

# Restore the main table.  I flushed it because OpenVPN does weird things to it.
ip route add 127.0.0.0/8 via 127.0.0.1 dev lo
ip route add 192.168.1.0/24 dev eth1 src 192.168.1.73
ip route add default via 192.168.1.254

# Set up table 21.  This sends all traffic to eth1.
ip route add 192.168.1.0/24 dev eth1 table 21
ip route add default via 192.168.1.254 dev eth1 table 21

# Set up table 11.  I honestly don't know why 'default' won't work, or
# why the second line here is needed.  But it works this way.
ip route add 10.32.0.49/32 dev tun0 table 11
ip route add 10.32.0.1 via 10.32.0.50 dev tun0 table 11
ip route add 0.0.0.0/1 via 10.32.0.50 dev tun0 table 11

ip route flush cache

## MeanderingCode edit (karena saya belum bisa berkomentar)

Terima kasih atas jawaban ini! Sepertinya ini bisa menjadi berantakan, karena Anda harus menjaga info rute di sini (mungkin menduplikasi, atau menghancurkan hal-hal lain yang mungkin ingin mengatur rute.

Anda mungkin mengalami "hal-hal aneh" di tabel perutean Anda dari OpenVPN karena server dikonfigurasi untuk "mendorong" rute, memungkinkan semua lalu lintas untuk merutekan melalui antarmuka jaringan VPN, daripada internet "telanjang". Atau konfigurasi OpenVPN Anda atau skrip / aplikasi apa pun yang mengaturnya adalah mengatur rute.

Dalam kasus sebelumnya, Anda dapat mengedit konfigurasi OpenVPN Anda dan memasukkan baris yang berisi "route-nopull"
Pada yang terakhir, periksa konfigurasi untuk OpenVPN atau pembungkus apa pun (network-manager-openvpn, misalnya pada banyak distro desktop linux saat ini)
Di apa pun kasusnya, menghilangkan konfigurasi perutean di mana pengaturannya lebih bersih dan lebih aman daripada membersihkan meja, tergantung pada saat Anda menjalankan skrip ini dan apa lagi yang dilakukan sistem Anda.

Tepuk tangan!

Ethan
sumber
2

Saya pikir Anda ingin:

/sbin/ip route add default via 10.32.0.49 dev tun0 table 11
/sbin/ip rule add priority 10000 fwmark 11 table 11

http://lartc.org/howto/lartc.netfilter.html

Tapi saya belum menguji di atas.

mfarver
sumber
Perintah pertama mengembalikan "Kesalahan:" ke "adalah duplikat, atau" 10.32.0.49 "adalah sampah."
Ethan
Maaf lupa via antara default dan IP.
mfarver
Saya mencobanya. Tampaknya memiliki efek yang sama dengan meninggalkan defaultkata kunci.
Ethan
Untuk menghilangkan opsi, Anda dapat mencoba melakukan penangkapan paket pada tun0, dan melihat apakah paket berakhir pada antarmuka itu. tcpdump -i tun0 .. atau, apakah Anda perlu mendasarkannya pada ID pengguna? Bisakah Anda melakukannya berdasarkan alamat IP tujuan (lebih mudah)? route add <host jarak jauh> via 10.32.0.49
mfarver
Saya tidak dapat mendasarkan jika dari alamat IP tujuan - akan ada banyak dari mereka. Secara teoritis saya juga bisa mendasarkannya pada pid, tetapi itu bahkan lebih sulit, karena saya tidak akan tahu pid itu sampai daemon dimulai.
Ethan
0

Ini dapat dilakukan tanpa perintah iptables Jalankan perintah ip sederhana

Untuk uid 1002:

ip rule add uidrange 1002-1002 table 502

Tambahkan rute default untuk tabel 502 melalui antarmuka yang ingin Anda ucapkan

eth0 ip rule add default via a.b.c.d dev eth0
jainendra
sumber
Saya menguji perintah itu, dan itu tidak berhasil:Error: argument "uidrange" is wrong: Failed to parse rule type
kasperd
@kasperd Anda pasti dia salah melakukannya, karena itu berfungsi dengan baik untuk saya.
horseyguy