Chỉ định tuyến lưu lượng truy cập cụ thể thông qua VPN


11

Tôi đã tra cứu những người trước đó hỏi những câu hỏi tương tự, nhưng vẫn chưa nhận được câu trả lời thẳng nào phù hợp với tình huống của tôi, vì vậy hãy đến đây ..

Tôi đang chạy trên Linux (Fedora 22) và có dịch vụ VPN mà tôi phải trả tiền, tuy nhiên tôi chỉ cần các chương trình cụ thể để sử dụng VPN cho lưu lượng truy cập internet của họ và có thể sử dụng kết nối ISP tiêu chuẩn của tôi cho mọi thứ khác (ví dụ: duyệt web, Vân vân)

Chúng tôi sẽ làm điều này đơn giản và giới hạn nó trong chương trình được sử dụng nhiều nhất, World of Warcraft, đang được điều hành thông qua WINE.

Bây giờ, tôi đã thiết lập VPN qua giao diện mạng để tất cả lưu lượng truy cập của tôi thông qua enp10s0 (tên lạ của máy tính cho eth0) có thể được chuyển qua dịch vụ VPN, tuy nhiên, tôi chỉ cần các chương trình cụ thể (hoặc cổng mà các chương trình đó sử dụng, để cụ thể) để đi qua VPN.

Làm cách nào để thiết lập đường hầm và chỉ định tuyến các cổng cần thiết thông qua VPN, trong khi vẫn giữ mọi thứ khác không bị định tuyến?


Bạn có thể giải thích làm thế nào các câu trả lời khác không giải quyết vấn đề này? Có gì độc đáo về thiết lập của bạn?
Paul

1
Hầu hết mỗi người trong số họ có một cách khác nhau để thực hiện điều này, và không ai trong số họ làm cho nó đơn giản cả. Một số sử dụng một không gian tên riêng biệt cho ứng dụng, một số sử dụng giao diện đường hầm, một số sử dụng thông qua openvpn trong một thiết bị đầu cuối, nhưng không ai trong số chúng tôi tìm thấy đã cho tôi bất kỳ phương pháp giải mã nào để thực hiện bất kỳ phương pháp nào có thể giải mã được.
Josh Raymond

Vui lòng xem Chỉnh sửa của tôi
MariusMatutiae

Câu trả lời:


17

Những gì bạn đang yêu cầu không tồn tại. Đây là lý do tại sao bạn không hài lòng với câu trả lời bạn tìm thấy (một số trong số chúng, có thể là của tôi): tất cả chúng đều có đề xuất giải pháp , không phải là giải pháp chính hãng, đơn giản hoặc phức tạp.

Hãy để tôi giải thích. Định tuyến trong tất cả các hệ điều hành được xác định theo địa chỉ đích: bạn rất có thể có một số tuyến, nhưng sự lựa chọn giữa chúng không dựa trên ứng dụng gọi kết nối, mà chỉ dựa trên địa chỉ đích. Dấu chấm.

Hãy để tôi cho bạn một ví dụ không tầm thường. Khi máy khách VPN đã thiết lập kết nối đến máy chủ của nó, vẫn có thể định tuyến kết nối đến một trang web nhất định, ví dụ example.org, bên ngoài VPN. Nhưng tất cả các ứng dụng cố gắng truy cập địa chỉ đặc biệt đó sẽ được định tuyến bên ngoài VPN: bạn không thể có một số ứng dụng truy cập example.org thông qua VPN trong khi các ứng dụng khác vượt ra ngoài VPN.

Tình hình trở nên phong phú hơn với nhân Linux, cho phép định tuyến nguồn: điều này có nghĩa là bạn có thể có hai hoặc nhiều bảng định tuyến và sự lựa chọn giữa chúng dựa trên địa chỉ nguồn chứ không phải địa chỉ đích.

Một ví dụ không tầm thường: máy tính của tôi có hai dòng bên ngoài, với hai IP công khai riêng biệt. Nó có thể được liên lạc qua một trong hai giao diện, và điều quan trọng là các câu trả lời của tôi cho một kết nối nhất định sẽ chuyển qua cùng một giao diện mà kết nối được đưa ra: nếu không chúng sẽ bị loại bỏ vì không liên quan khi chúng đến người bắt đầu kết nối. Đây là định tuyến nguồn.

Đủ công bằng, những gì về kết nối mà chúng ta bắt đầu? Một số ứng dụng cho phép bạn chỉ định địa chỉ liên kết, như ứng dụng khách openssh :

-b bind_address

Sử dụng bind_address trên máy cục bộ làm địa chỉ nguồn của kết nối. Chỉ hữu ích trên các hệ thống có nhiều hơn một địa chỉ.

Đối với họ, không có vấn đề gì khi có một cá thể đi qua VPN (giả sử, bảng định tuyến 1) trong khi một phiên bản khác sẽ đi ra ngoài VPN (giả sử bảng định tuyến 2). Nhưng các ứng dụng khác, như Firefox, không chỉ khó liên kết với một địa chỉ IP nguồn cụ thể (mà hãy xem ở đây để có cách giải quyết rất thông minh), mà còn có ý nghĩa và khó chịu ở chỗ chúng sẽ không cho phép bạn có hai bản sao của chúng chạy đồng thời, mỗi ràng buộc với một địa chỉ nguồn khác nhau. Nói cách khác, nhờ vào thủ thuật được tham chiếu ở trên, bạn có thể bắt buộc một trường hợp phải liên kết với một địa chỉ nguồn bạn chọn, sau đó bạn không thể có một phiên bản khác của nó liên kết với địa chỉ nguồn khác.

Điều này giải thích tại sao chúng tôi sử dụng cách giải quyết: tất cả chúng đều dựa trên cùng một ý tưởng, rằng chúng hoạt động với một ngăn xếp mạng riêng biệt so với phần còn lại của máy tính. Vì vậy, bạn có thể có, theo thứ tự gần đúng về độ phức tạp, VM, docker, container, không gian tên. Trong mỗi bảng, bạn sẽ có một hoặc nhiều bảng định tuyến, nhưng bạn có thể có một vài phiên bản của mỗi (VM / docker / container / tên không gian) và bạn cũng có thể trộn chúng một cách tự do, mỗi bảng chạy ứng dụng riêng như Firefox vui vẻ tách ra từ những người khác.

Có lẽ bạn vẫn quan tâm đến một trong những cách giải quyết?

BIÊN TẬP:

Cách làm việc đơn giản nhất là một không gian tên mạng. Kịch bản bên dưới xử lý tất cả các khía cạnh cần thiết của NNS: đặt nó vào một tệp (bạn chọn tên của mình, tôi thường sử dụng newns, nhưng bạn làm bất cứ điều gì bạn thích) /usr/local/bin, sau đó chmod 755 FILE_NAME, và bạn có thể sử dụng nó như sau:

       newns NAMESPACE_NAME start
       newns NAMESPACE_NAME stop

Nó sẽ mở ra xtermcho bạn (đó là vì tôi thích xterm hoạt động, nhưng bạn có thể thay đổi nó nếu bạn muốn sử dụng bất cứ thứ gì khác), thuộc về không gian tên mới. Từ bên trong xterm bạn có thể, nếu bạn muốn, bắt đầu vpn của bạn, và sau đó bắt đầu trò chơi của bạn. Bạn có thể dễ dàng kiểm tra xem bạn có đang sử dụng VPN thông qua lệnh sau không:

    wget 216.146.38.70:80 -O - -o /dev/null | cut -d" " -f6 | sed 's/<\/body><\/html>//'

trả về cho bạn IP công cộng của bạn. Sau khi thiết lập VPN trong xterm, bạn có thể kiểm tra xem IP công khai của bạn có khác trong các cửa sổ khác không. Bạn có thể mở tối đa 254 xterms, với 254 NNS khác nhau và các kết nối khác nhau.

#!/bin/bash

#
# This script will setup an internal network 10.173.N.0/24; if this causes
# any conflict, change the statement below.

export IP_BASE=10.173

# It will open an xterm window in the new network namespace; if anything
# else is required, change the statement below.

export XTERM=/usr/bin/xterm

# The script will temporarily activate ip forwarding for you. If you
# do not wish to retain this feature, you will have to issue, at the 
# end of this session, the command
# echo 0 > /proc/sys/net/ipv4/ip_forward 
# yourself. 

 ###############################################################################

 WHEREIS=/usr/bin/whereis

 # First of all, check that the script is run by root:


 [ "root" != "$USER" ] && exec sudo $0 "$@"

 if [ $# != 2 ]; then
    echo "Usage $0 name action"
    echo "where name is the network namespace name,"
    echo " and action is one of start| stop| reload."
    exit 1
 fi

 # Do we have all it takes?

 IERROR1=0
 IERROR2=0
 IERROR3=0
 export IP=$($WHEREIS -b ip | /usr/bin/awk '{print $2}')
 if [ $? != 0 ]; then
    echo "please install the iproute2 package"
    IERROR1=1
 fi

 export IPTABLES=$($WHEREIS -b iptables | /usr/bin/awk '{print $2}')
 if [ $? != 0 ]; then
    echo "please install the iptables package"
    IERROR2=1
 fi

 XTERM1=$($WHEREIS -b $XTERM | /usr/bin/awk '{print $2}')
 if [ $? != 0 ]; then
    echo "please install the $XTERM package"
    IERROR3=1
 fi
 if [ IERROR1 == 1 -o IERROR2 == 1 -o IERROR3 == 1 ]; then
    exit 1
 fi

 prelim() {

 # Perform some preliminary setup. First, clear the proposed 
 # namespace name of blank characters; then create a directory
 # for logging info, and a pid file in it; then determine 
 # how many running namespaces already exist, for the purpose
 # of creating a unique network between the bridge interface (to 
 # be built later) and the new namespace interface. Lastly, 
 # enable IPv4 forwarding. 

    VAR=$1
    export NNSNAME=${VAR//[[:space:]]}

    export OUTDIR=/var/log/newns/$NNSNAME

    if [ ! -d $OUTDIR ]; then
            /bin/mkdir -p $OUTDIR
    fi
    export PID=$OUTDIR/pid$NNSNAME

    # Find a free subnet

    ICOUNTER=0
    while true; do
            let ICOUNTER=ICOUNTER+1
            ip addr show | grep IP_BASE.$ICOUNTER.1 2>&1 1> /dev/null
            if [ ! $? == 0 -a $ICOUNTER -lt 255 ]; then
                    export Nns=$ICOUNTER
                    break
            elif [ ! $? == 0 -a $ICOUNTER -gt 254 ]; then
                    echo "Too many open network namespaces"
                    exit 1
            fi
    done
    if [ $Nns == 1 ]; then
            echo 1 > /proc/sys/net/ipv4/ip_forward
    fi

 }

 start_nns() {

 # Check whether a namespace with the same name already exists. 

    $IP netns list | /bin/grep $1 2> /dev/null
    if [ $? == 0 ]; then
            echo "Network namespace $1 already exists,"
            echo "please choose another name"
            exit 1
    fi

    # Here we take care of DNS

    /bin/mkdir -p /etc/netns/$1
    echo "nameserver 8.8.8.8" > /etc/netns/$1/resolv.conf
    echo "nameserver 8.8.4.4" >> /etc/netns/$1/resolv.conf


    # The following creates the new namespace, the veth interfaces, and
    # the bridge between veth1 and a new virtual interface, tap0.
    # It also assigns an IP address to the bridge, and brings everything up

    $IP netns add $1
    $IP link add veth-a$1 type veth peer name veth-b$1
    $IP link set veth-a$1 up
    $IP tuntap add tap$1 mode tap user root
    $IP link set tap$1 up
    $IP link add br$1 type bridge
    $IP link set tap$1 master br$1
    $IP link set veth-a$1 master br$1
    $IP addr add $IP_BASE.$Nns.1/24 dev br$1
    $IP link set br$1 up

    # We need to enable NAT on the default namespace

    $IPTABLES -t nat -A POSTROUTING -j MASQUERADE

    # This assigns the other end of the tunnel, veth2, to the new 
    # namespace, gives it an IP address in the same net as the bridge above, 
    # brings up this and the (essential) lo interface, sets up the 
    # routing table by assigning the bridge interface in the default namespace
    # as the default gateway, creates a new terminal in the new namespace and 
    # stores its pid for the purpose of tearing it cleanly, later. 

    $IP link set veth-b$1 netns $1
    $IP netns exec $1 $IP addr add $IP_BASE.$Nns.2/24 dev veth-b$1
    $IP netns exec $1 $IP link set veth-b$1 up
    $IP netns exec $1 $IP link set dev lo up
    $IP netns exec $1 $IP route add default via $IP_BASE.$Nns.1
    $IP netns exec $1 su -c $XTERM $SUDO_USER &
    $IP netns exec $1 echo "$!" > $PID



}

stop_nns() {

# Check that the namespace to be torn down really exists

    $IP netns list | /bin/grep $1 2>&1 1> /dev/null
    if [ ! $? == 0 ]; then
            echo "Network namespace $1 does not exist,"
            echo "please choose another name"
            exit 1
    fi

    # This kills the terminal in the separate namespace, 
    # removes the file and the directory where it is stored, and tears down
    # all virtual interfaces (veth1, tap0, the bridge, veth2 is automatically
    # torn down when veth1 is), and the NAT rule of iptables. 

    /bin/kill -TERM $(cat $PID) 2> /dev/null 1> /dev/null
    /bin/rm $PID
    /bin/rmdir $OUTDIR
    $IP link set br$1 down
    $IP link del br$1
    $IP netns del $1
    $IP link set veth-a$1 down
    $IP link del veth-a$1
    $IP link set tap$1 down
    $IP link del tap$1
    $IPTABLES -t nat -D POSTROUTING -j MASQUERADE
    /bin/rm /etc/netns/$1/resolv.conf
    /bin/rmdir /etc/netns/$1

}


case $2 in
    start)
            prelim "$1"
            start_nns $NNSNAME
            ;;
    stop)
            prelim "$1"
            stop_nns $NNSNAME
            ;;
    reload)
            prelim "$1"
            stop_nns $NNSNAME
            prelim "$1"
            start_nns $NNSNAME
            ;;
    *)
 # This removes the absolute path from the command name

            NAME1=$0
            NAMESHORT=${NAME1##*/}

            echo "Usage:" $NAMESHORT "name action,"
            echo "where name is the name of the network namespace,"
            echo "and action is one of start|stop|reload"
            ;;
 esac

Nếu bạn muốn, bạn thậm chí có thể bắt đầu toàn bộ máy tính để bàn bên trong không gian tên mạng mới, bằng phương tiện

            sudo startx -- :2 

sau đó bạn có thể tìm kiếm nó bằng cách sử dụng Alt+ Ctrl+ Fn, trong đó Fn là một trong những F1, F2, ....-

Tôi cần thêm một cảnh báo: Xử lý DNS bên trong không gian tên là một lỗi nhỏ, hãy kiên nhẫn.


1
Và do đó, cuối cùng tôi đã có một lời giải thích rất đơn giản nhưng chi tiết về lý do tại sao những gì tôi đang cố gắng thực hiện lại không dễ dàng cũng không phổ biến! Cảm ơn bạn! Đọc xong, tôi tin rằng một cách giải quyết sẽ phù hợp, vì đó chỉ là lưu lượng truy cập từ một chương trình cụ thể mà tôi muốn định tuyến và tôi luôn muốn chương trình đó được định tuyến. Ví dụ: Tôi muốn VideoGameA được định tuyến qua VPN, nhưng tôi không muốn bất kỳ chương trình nào khác được chuyển qua nó. Có cách nào đơn giản để liên kết các cổng cụ thể chỉ đi qua giao diện VPN không? Nếu vậy, làm thế nào để tôi thiết lập đúng và kết nối với giao diện đã nói?
Josh Raymond

@JoshRaymond Ok. Để chọn cách giải quyết đơn giản nhất, bạn nên đăng bảng định tuyến của mình bằng VPN và nên cho tôi biết liệu VideoGameA có sử dụng cổng UDP hay không.
MariusMatutiae

Nó sử dụng cả hai cổng TCP và UDP 443, 3724 và 1119 Tuyến sẽ được đăng trong phần tiếp theo
Josh Raymond

$ route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 0.0.0.0 0.0.0.0 U 50 0 0 ppp0 0.0.0.0 192.168.1.1 0.0.0.0 UG 100 0 0 enp10s0 1.0.0.1 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0 192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 enp10s0 192.168.1.0 0.0.0.0 255.255.255.0 U 100 0 0 enp10s0 199.168.112.120 192.168.1.1 255.255.255.255 UGH 100 0 0 enp10s0
Josh Raymond

Tôi đang tự hỏi tại sao trong câu trả lời @MariusMatutiae lại tạo ra một cái vòi và một cây cầu? Nó dường như hoạt động tốt chỉ bằng cách sử dụng các thiết bị veth.
Ian Kelling
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.