iptables - Nhắm mục tiêu định tuyến gói đến giao diện cụ thể?


25

Máy chủ gia đình của tôi có hai giao diện chính, eth1(kết nối internet tiêu chuẩn) và tun0(đường hầm OpenVPN). Tôi muốn sử dụng iptablesđể buộc tất cả các gói được tạo bởi một quy trình cục bộ thuộc sở hữu của UID 1002 để thoát qua tun0và tất cả các gói khác để thoát qua eth1.

Tôi có thể dễ dàng đánh dấu các gói phù hợp:

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

Bây giờ, tôi muốn đặt một số quy tắc trong chuỗi POSTROUTING (có thể là bảng mangle) để khớp các gói được đánh dấu bằng 11 và gửi chúng đến tun0, theo sau là một quy tắc khớp với tất cả các gói và gửi chúng đến eth1.

Tôi đã tìm thấy mục tiêu ROUTE, nhưng dường như chỉ viết lại giao diện nguồn (trừ khi tôi đọc không chính xác).

Là iptables có khả năng này? Thay vào đó, tôi có phải loay hoay với bảng định tuyến (thông qua ip routehoặc chỉ các routelệnh kế thừa ) không?

Chỉnh sửa: Tôi nghĩ rằng có lẽ tôi nên cung cấp thêm thông tin. Hiện tại tôi không có quy tắc iptables nào khác (mặc dù tôi có thể tạo một số quy tắc để thực hiện các nhiệm vụ không liên quan trong tương lai). Ngoài ra, đầu ra của ip routelà:

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

Tôi chưa chạm vào bảng định tuyến - đây chỉ là cách nó hiện tại (mặc dù nó trông khá bẩn). Tôi xin lỗi, nhưng tôi không routecài đặt lệnh kế thừa trên máy này.

Và đầu ra của ip addr(tất nhiên, eth0 và eth2 có thể bị bỏ qua - chúng là các NIC hiện không được sử dụng):

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

Chỉnh sửa: Tôi đã nhận được một cái gì đó sắp xếp hoạt động, nhưng nó không chuyển tiếp các gói được đánh dấu đến tun0. Về cơ bản, tôi đã thêm một bảng (11) và được sử dụng:

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

Khi tôi chỉ sudo -u user1000 wget -qO- whatismyip.org, tôi nhận được địa chỉ IP bên ngoài của nhà tôi, nhưng nếu có sudo -u user1002 wget -qO- whatismyip.org, tôi cũng nhận được địa chỉ IP của nhà tôi (nhưng tôi sẽ nhận được IP ở đầu kia của đường hầm OpenVPN).

Chạy iptables -vLxác nhận rằng các gói đang được khớp với quy tắc đánh dấu, nhưng chúng dường như không tuân theo quy tắc định tuyến.

EDIT: Tôi đã dành một thời gian dài cho việc này, và mặc dù nó vẫn không hoạt động, tôi nghĩ rằng tôi gần hơn một chút.

Quy tắc iptables phải nằm trong manglechuỗi OUTPUT của bảng. Tôi nghĩ rằng tôi cũng cần một quy tắc MASQUERADE trong natchuỗi POSTROUTING của bảng để đặt địa chỉ nguồn. Tuy nhiên, việc định tuyến lại xảy ra sau khi mangle của OUTPUT không hoạt động chính xác.

Tôi đã dành 5 giờ cho việc này bây giờ, vì vậy tôi đang nghỉ ngơi và có thể sẽ quay lại vào tối nay hoặc đôi khi vào ngày mai.

Câu trả lời:


26

Gần đây tôi đã gặp một vấn đề tương tự, mặc dù có một chút khác biệt. Tôi muốn con đường duy nhất cổng TCP 25 (SMTP) trên một giao diện tap0 OpenVPN, trong khi định tuyến tất cả lưu lượng khác (ngay cả đối với cùng một máy chủ) so với giao diện mặc định.

Để làm như vậy, tôi phải đánh dấu các gói và thiết lập các quy tắc để xử lý nó. Đầu tiên, thêm một quy tắc làm cho các gói tuyến nhân được đánh dấu 2thông qua bảng 3(giải thích sau):

ip rule add fwmark 2 table 3

Bạn có thể đã thêm một tên tượng trưng cho /etc/iproute2/rt_tables, nhưng tôi không bận tâm làm điều đó. Số lượng 23được chọn ngẫu nhiên. Trong thực tế, những điều này có thể giống nhau nhưng để rõ ràng tôi đã không làm điều đó trong ví dụ này (mặc dù tôi làm điều đó trong thiết lập của riêng tôi).

Thêm tuyến đường để chuyển hướng lưu lượng truy cập qua một giao diện khác, giả sử cổng là 10.0.0.1:

ip route add default via 10.0.0.1 table 3

Rất quan trọng! Xóa bộ nhớ cache định tuyến của bạn, nếu không bạn sẽ không nhận được phản hồi và ngồi với tay trong tóc trong vài giờ:

ip route flush cache

Bây giờ, đặt quy tắc tường lửa để đánh dấu các gói được chỉ định:

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

Quy tắc trên chỉ áp dụng nếu các gói đến từ máy cục bộ. Xem http://inai.de/images/nf-packet-flow.png . Điều chỉnh nó theo yêu cầu của bạn. Chẳng hạn, nếu bạn chỉ muốn định tuyến lưu lượng HTTP đi qua tap0giao diện, hãy thay đổi 465 thành 80.

Để ngăn các gói được gửi qua tap0lấy địa chỉ LAN của bạn làm IP nguồn, hãy sử dụng quy tắc sau để thay đổi địa chỉ thành địa chỉ giao diện của bạn (giả sử 10.0.0.2là địa chỉ IP cho giao diện tap0):

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

Cuối cùng, thư giãn xác nhận nguồn đường dẫn ngược. Một số gợi ý bạn nên đặt nó 0, nhưng 2có vẻ như là một lựa chọn tốt hơn theo https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt . Nếu bạn bỏ qua điều này, bạn sẽ nhận được các gói (điều này có thể được xác nhận bằng cách sử dụng tcpdump -i tap0 -n), nhưng các gói không được chấp nhận. Lệnh thay đổi cài đặt để các gói được chấp nhận:

sysctl -w net.ipv4.conf.tap0.rp_filter=2

Tại sao bạn sử dụng SNAT thay vì MASQUERADE? Không phải MASQUERADE làm điều tương tự, ngoại trừ địa chỉ IP được thu thập từ giao diện tại "runtime" và không được mã hóa cứng vào tập tin cấu hình?
Ethan

6
@Ethan From man iptables: Chỉ nên được sử dụng với các kết nối IP (quay số) được gán động: nếu bạn có địa chỉ IP tĩnh, bạn nên sử dụng mục tiêu SNAT. Masquerading tương đương với việc chỉ định ánh xạ tới địa chỉ IP của giao diện mà gói tin bị tắt, nhưng cũng có tác dụng khiến các kết nối bị lãng quên khi giao diện bị hỏng. Bạn đúng, nhưng vì IP của tôi sẽ không bao giờ thay đổi, tôi đã quyết định sử dụng SNAT theo đề xuất của trang này.
Lekensteyn

Tôi nghĩ (mặc dù không được kiểm tra) bước cuối cùng (xác thực nguồn đường dẫn ngược) là không cần thiết. Bạn chỉ có thể thêm một quy tắc khác vào PREROUTINGchuỗi vào DNATđịa chỉ nguồn chính xác (theo cổng mặc định của bạn).
Christian Wolf

7

Tôi đã giải quyết điều này. Vấn đề là với các quy tắc định tuyến trong bảng 11. Bảng 11 đã bị ảnh hưởng, nhưng các quy tắc định tuyến làm cho nó không thể hoạt động. Kịch bản này là những gì tôi hiện đang sử dụng và dường như nó hoạt động tốt (mặc dù nó rõ ràng là cụ thể cho thiết lập của tôi). Ngoài ra, tôi đã tạo một bảng 21 mới dành cho đường lên chính (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 chỉnh sửa (vì tôi chưa thể nhận xét)

Cảm ơn câu trả lời này! Có vẻ như điều này có thể trở nên lộn xộn, vì bạn sẽ phải duy trì thông tin tuyến đường ở đây (có thể trùng lặp hoặc phá vỡ những thứ khác có thể muốn đặt tuyến.

Bạn có thể gặp phải "những điều kỳ lạ" trong bảng định tuyến của mình từ OpenVPN vì máy chủ được định cấu hình để "đẩy" các tuyến, cho phép tất cả lưu lượng truy cập qua giao diện mạng VPN, thay vì internet "trần". Hoặc cấu hình OpenVPN của bạn hoặc bất kỳ tập lệnh / ứng dụng nào thiết lập nó đang thiết lập các tuyến đường.

Trong trường hợp thứ nhất, bạn có thể chỉnh sửa cấu hình OpenVPN của bạn và đặt trong một dòng có chứa "đường-nopull"
trong, cấu hình kiểm tra sau cho OpenVPN hoặc bất kỳ wrapper (network-manager-openvpn, ví dụ trên nhiều distro máy tính để bàn Linux hiện hành)
trong trong cả hai trường hợp, loại bỏ cấu hình định tuyến nơi cài đặt sẽ sạch hơn và an toàn hơn so với xóa bảng, tùy thuộc vào thời điểm bạn chạy tập lệnh này và hệ thống của bạn đang làm gì khác.

Chúc mừng!


2

Tôi nghĩ bạn muốn:

/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

Nhưng tôi đã không kiểm tra ở trên.


Lệnh đầu tiên trả về "Lỗi:" hoặc "là trùng lặp hoặc" 10.32.0.49 "là rác."
Ethan

Xin lỗi đã quên thông qua giữa mặc định và IP.
mfarver

Tôi đã thử nó. Nó dường như có tác dụng tương tự như bỏ defaulttừ khóa ra.
Ethan

Để loại bỏ các tùy chọn, bạn có thể thử thực hiện chụp gói trên tun0 và xem các gói có kết thúc trên giao diện đó không. tcpdump -i tun0 .. thay vào đó, bạn có cần căn cứ vào ID người dùng không? Bạn có thể làm điều đó dựa trên địa chỉ IP đích (dễ dàng hơn) không? tuyến đường thêm <máy chủ từ xa> qua 10.32.0,49
mfarver

Tôi không thể căn cứ nếu tắt địa chỉ IP đích - sẽ có nhiều địa chỉ. Về mặt lý thuyết tôi cũng có thể căn cứ vào điều đó, nhưng điều đó thậm chí còn khó khăn hơn, bởi vì tôi sẽ không biết đến điều đó cho đến khi daemon bắt đầu.
Ethan

0

Điều này có thể được thực hiện mà không có lệnh iptables Thực thi lệnh ip đơn giản

Đối với 1002:

ip rule add uidrange 1002-1002 table 502

Thêm tuyến mặc định cho bảng 502 qua giao diện mà bạn muốn nói

eth0 ip rule add default via a.b.c.d dev eth0

Tôi đã thử lệnh đó và nó không hoạt động:Error: argument "uidrange" is wrong: Failed to parse rule type
kasperd

@kasperd bạn phải làm sai, vì nó hoạt động tốt với tôi.
Horseyguy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.