Định tuyến lưu lượng truy cập qua giao diện cụ thể cho một quy trình trong linux


20

Có thể định tuyến lưu lượng truy cập được sử dụng bởi một quy trình qua một giao diện cụ thể không?

Ví dụ: lưu lượng truy cập mạng bằng ứng dụng tải xuống phải luôn sử dụng giao diện wlan0trong khi tất cả các ứng dụng khác trên máy nên sử dụng eth0.

Có thể có loại quy tắc này trong Linux không?

Câu trả lời:


22

Nó có thể được thực hiện bằng cách sử dụng không gian mạng Linux.

Dưới đây là một bài viết giải thích làm thế nào. Về cơ bản, bạn tạo một không gian tên mạng với một tuyến mặc định khác và chạy các quy trình cần nó ở đó. Bạn kết nối không gian tên mạng mới được tạo với bộ điều hợp vật lý bằng một cây cầu (tất nhiên là có thể có các giải pháp khác).

Cập nhật: từ kernel 3.14 thậm chí còn dễ dàng hơn khi sử dụng các nhóm điều khiển, như được mô tả trong bài viết này . Bạn phải:

1) xác định nhóm điều khiển net_cls để chú thích các gói từ một quy trình nhất định với một classid (hoặc nhóm quy trình, lưu ý rằng không có bất kỳ mối quan hệ cha-con nào giữa chúng)

2) sử dụng mô đun cpt iptables (được thêm vào Linux 3.14) để đánh dấu các gói

3) sử dụng định tuyến chính sách (quy tắc ip thêm fwmark ....) để tạo bảng định tuyến mới cho các gói được đánh dấu

Ưu điểm là chúng ta không phải làm điều bắc cầu và mọi thứ năng động hơn rất nhiều nhờ vào các nhóm.


14

Tôi đã phải vật lộn với điều này vì vậy đây là một giải pháp HOÀN THÀNH. Nó đã được thử nghiệm trên Ubuntu 15 & 16. Bạn có thể đặc biệt sử dụng nó với OpenVPN để định tuyến các ứng dụng nhất định bên ngoài giao diện đường hầm VPN.

Giải pháp "cgroup" hoàn chỉnh

Làm thế nào mà hoạt động?

  • Nhân Linux sẽ đưa ứng dụng vào nhóm kiểm soát . Lưu lượng truy cập mạng từ các ứng dụng trong nhóm này sẽ được xác định bởi ID lớp của chúng ở cấp điều khiển mạng.
  • iptables sẽ đánh dấu lưu lượng này và buộc nó phải thoát với đúng IP
  • tuyến ip sẽ xử lý lưu lượng được đánh dấu trong một bảng định tuyến khác, với tuyến mặc định tới bất kỳ IP cổng nào bạn muốn.

Kịch bản tự động

Tôi đã tạo một tập lệnh novpn.sh để tự động cài đặt và chạy phụ thuộc. Đã thử nghiệm trên Ubuntu.

Bắt đầu VPN của bạn trước.

wget https://gist.githubusercontent.com/kriswebdev/a8d291936fe4299fb17d3744497b1170/raw/cf8b37fbe6c3f50a0be825eb77cafa3e0134946f/novpn.sh
# If you don't use eth0, edit the script setting.
sudo chmod +x novpn.sh
./novpn.sh traceroute www.google.com
./novpn.sh --help

Hướng dẫn cách làm

Đầu tiên, cài đặt các công cụ và hỗ trợ cgroup:

sudo apt-get install cgroup-lite cgmanager cgroup-tools

Khởi động lại (có thể không cần thiết).

Bạn cần iptables 1.6 .0+. Nhận nguồn phát hành iptables 1.6.0 , giải nén nó, sau đó chạy này ( --disable-nftablescờ sẽ tránh lỗi) từ thư mục nguồn iptables:

sudo apt-get install dh-autoreconf bison flex
./configure --prefix=/usr      \
            --sbindir=/sbin    \
            --disable-nftables \
            --enable-libipq    \
            --with-xtlibdir=/lib/xtables
make
sudo make install
iptables --version

Bây giờ, cấu hình thực sự. Xác định một nhóm kiểm soát có tên novpn. Các quy trình trong nhóm này sẽ có một lớp 0x00110011(11:11).

sudo su
mkdir /sys/fs/cgroup/net_cls/novpn
cd /sys/fs/cgroup/net_cls/novpn
echo 0x00110011 > net_cls.classid

Bây giờ, chúng tôi sẽ giả sử giao diện bạn muốn sử dụng cho ứng dụng cụ thể eth0có IP cổng 10.0.0.1. Thay thế những thứ này bằng những gì bạn thực sự muốn (lấy thông tin từ ip route). Chạy vẫn như root:

# Add mark 11 on packets of classid 0x00110011
iptables -t mangle -A OUTPUT -m cgroup --cgroup 0x00110011 -j MARK --set-mark 11

# Force the packets to exit through eth0 with NAT
iptables -t nat -A POSTROUTING -m cgroup --cgroup 0x00110011 -o eth0 -j MASQUERADE

# Define a new "novpn" routing table
# DO THIS JUST ONCE !
echo 11 novpn >> /etc/iproute2/rt_tables

# Packets with mark 11 will use novpn
ip rule add fwmark 11 table novpn

# Novpn has a default gateway to the interface you want to use
ip route add default via 10.0.0.1 table novpn

# Unset reverse path filtering for all interfaces, or at least for "eth0" and "all"
for i in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $i; done

Cuối cùng, chạy ứng dụng của bạn trên giao diện cụ thể:

exit
sudo cgcreate -t $USER:$USER -a $USER:$USER -g net_cls:novpn
cgexec -g net_cls:novpn traceroute www.google.com
# Close all Firefox windows first
cgexec -g net_cls:novpn firefox

Hoặc nếu bạn muốn chuyển một quy trình đã chạy sang nhóm, thì ... bạn không thể! Điều đó dường như là do chức năng NAT (giả trang): iptables -nvL -t natkhông khớp khi cgroup được chuyển đổi, nhưng iptables -nvL -t manglekhông khớp.

# Get PID of the process (we'll then suppose it's 1234)
pidof firefox
# Add to cgroup - THIS DOESN'T WORK! Silently fails to produce the final result.
sudo echo 1234 > /sys/fs/cgroup/net_cls/novpn/tasks
# Remove - but this works...
sudo echo 1234 > /sys/fs/cgroup/net_cls

Tín dụng: Không có câu trả lời nào hoạt động như mong đợi, nhưng một hỗn hợp của chúng đã làm: chripell answer evolware article Mỗi quá trình định tuyến mất 2: sử dụng cgroups, iptables và định tuyến chính sách , Làm cách nào để tạo một quy trình cụ thể KHÔNG đi qua kết nối OpenVPN? , Kill switch cho OpenVPN trên cơ sở iptables


Cảm ơn câu trả lời tuyệt vời, làm thế nào để tôi làm cho nó hoạt động với apache? Tôi đã thử cgexec -g net_cls:novpn apache2và đưa cho tôi toàn bộ danh sách các biến số không xác định!
razzak

2
Bạn sẽ nhận được các lỗi tương tự bằng cách chạy apache2trực tiếp từ thiết bị đầu cuối. Đó là bởi vì apache2thường được ra mắt như một dịch vụ, với systemctl start apache2. Tuy nhiên, điều đó sẽ không làm việc với cgexec. Chương trình được gọi phải là cha mẹ của apache2quá trình ( ) mong muốn để nhóm net_cls truyền bá. Vì vậy, bạn cần phải tìm kịch bản khởi chạy. Trong trường hợp này, nó sudo cgexec -g net_cls:novpn /usr/sbin/apache2ctl start. Kiểm tra với ./novpn.sh --list.
KrisWebDev

Nó không hoạt động trong Ubuntu 16.04 nữa!
razzak

2
Tôi đang sử dụng nó trên Ubuntu 16.04 và nó hoạt động tốt. Tên giao diện đã thay đổi trong Ubuntu 16, bạn có thể cần thay thế eth0bằng một cái gì đó như enp7s0. Lấy thông tin từ ifconfiglệnh.
KrisWebDev

Cảm ơn bạn. Nhưng nó không hoạt động trên Ubuntu 18.04 vì cpmanager đã bị xóa do xung đột với systemd
skonsoft


3

Kết hợp các câu trả lời xuất sắc của mariusmatutiae và KrisWebDev Tôi đã tạo ra một phiên bản sửa đổi rộng rãi novpn.shkịch bản tuyệt vời của KrisWebDev . Trong khi tập lệnh của KrisWebDev được thiết kế để gãi một vết ngứa cụ thể hơn (chạy và di chuyển các quy trình bên trong / bên ngoài VPN), phiên bản của tôi cho phép bạn chạy về cơ bản bất kỳ lệnh nào trong môi trường mạng mà bạn chỉ định. Bạn có thể chỉ định giao diện để liên kết, tuyến mặc định, chỉ định quy tắc iptables của riêng bạn, tuyến tĩnh, chỉ định "kiểm tra" để xác nhận mọi thứ đang hoạt động như bạn mong muốn trước khi chạy lệnh ... vv). Nó cho phép bạn sử dụng nhiều tệp cấu hình để bạn có thể xác định bất kỳ số lượng môi trường mạng cụ thể nào mà bạn có thể chạy các lệnh / quy trình bên trong.

Tôi đã đăng nó dưới dạng ý chính ở đây: https://gist.github.com/level323/54a921216f0baaa163127d960bfebbf0

Nó thậm chí có thể dọn sạch các bảng cgroup / iptables / định tuyến sau đó!

Phản hồi chào mừng.

PS - Nó được thiết kế cho Debian 8 (Jessie)


Xin chào @allnatural, tôi muốn sử dụng tập lệnh altnetworking.sh của bạn, nhưng tôi nên đưa gì vào tập tin cấu hình?
Cris70

0

Không phải mỗi ứng dụng, không. Bạn có thể làm điều đó trên mỗi cổng hoặc mỗi địa chỉ IP, v.v. hoặc chính ứng dụng có thể liên kết với (và sử dụng) một card mạng cụ thể.

Bạn không thể thiết lập một quy tắc để làm điều đó mặc dù.


Tôi có một ứng dụng java, có thể liên kết ứng dụng đó với một giao diện không?
Suresh

Một ứng dụng Java bạn có mã nguồn và có thể lập trình lại các phần bên trong không?
Majenko

Tôi có một mã nguồn ứng dụng java sử dụng thư viện apache http.
Suresh

Sau đó, tôi sẽ đi đến stackoverflow.com và hỏi các lập trình viên ở đó cách thay đổi chương trình của bạn. Tôi chưa bao giờ lập trình bằng Java.
Majenko
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.