กำหนดเส้นทางการรับส่งข้อมูลเฉพาะผ่าน VPN


9

ฉันค้นหาคนก่อนหน้าเพื่อถามคำถามที่คล้ายกัน แต่ยังไม่ได้รับคำตอบที่ตรงกับสถานการณ์ของฉัน

ฉันกำลังใช้งานบน Linux (Fedora 22) และมีบริการ VPN ที่จ่ายไปฉันต้องใช้โปรแกรมเฉพาะเพื่อใช้งาน VPN สำหรับการรับส่งข้อมูลทางอินเทอร์เน็ตของพวกเขาและสามารถใช้การเชื่อมต่อ ISP มาตรฐานของฉันสำหรับทุกสิ่ง (เช่นการท่องเว็บ ฯลฯ )

เราจะทำให้มันง่ายและ จำกัด ให้เป็นโปรแกรมที่ใช้มากที่สุดคือ World of Warcraft ซึ่งกำลังทำงานผ่าน WINE

ตอนนี้ฉันมีการตั้งค่า VPN ผ่านอินเทอร์เฟซเครือข่ายเพื่อให้ปริมาณการใช้ข้อมูลทั้งหมดของฉันผ่าน enp10s0 (ชื่อคอมพิวเตอร์แปลก ๆ สำหรับ eth0) ของฉันสามารถถูกส่งผ่านบริการ VPN ได้อย่างไรก็ตามฉันต้องการเฉพาะโปรแกรม (หรือพอร์ตที่โปรแกรมเหล่านั้นใช้ เจาะจง) เพื่อใช้งาน VPN

ฉันจะตั้งค่าอุโมงค์ได้อย่างไรและกำหนดเส้นทางเฉพาะพอร์ตที่ต้องการผ่าน VPN ในขณะที่ไม่ได้กำหนดเส้นทางอื่นทุกอย่าง


คุณช่วยอธิบายว่าคำตอบอื่น ๆ ไม่ได้แก้ปัญหานี้ได้อย่างไร การตั้งค่าของคุณมีอะไรพิเศษ
Paul

1
เกือบทุกคนมีวิธีที่แตกต่างกันในการทำสิ่งนี้ให้สำเร็จและไม่มีใครทำแบบนั้นเลย บางคนใช้เนมสเปซแยกจากกันสำหรับแอปพลิเคชั่นบางตัวใช้ช่องสัญญาณอินเทอร์เฟซบางตัวส่งผ่าน openvpn ในเทอร์มินัล แต่ก็ไม่พบสิ่งใดเลย
Josh Raymond

โปรดดูการแก้ไขของฉัน
MariusMatutiae

คำตอบ:


12

สิ่งที่คุณจะขอไม่ได้อยู่ นี่คือเหตุผลที่คุณไม่พึงพอใจกับคำตอบที่คุณพบ (บางคำตอบอาจเป็นของฉัน): ทุกคำแนะนำมีวิธีแก้ไขไม่ใช่วิธีแก้ปัญหาของแท้ไม่ว่าจะง่ายหรือซับซ้อน

ให้ฉันอธิบาย การกำหนดเส้นทางในระบบปฏิบัติการทั้งหมดนั้นพิจารณาจากที่อยู่ปลายทาง: คุณอาจมีหลายเส้นทาง แต่ตัวเลือกระหว่างพวกเขาไม่ได้ขึ้นอยู่กับแอปพลิเคชันที่เรียกใช้การเชื่อมต่อ แต่ขึ้นอยู่กับที่อยู่ปลายทาง หยุดเต็ม

ผมขอยกตัวอย่างที่ไม่สำคัญ เมื่อไคลเอนต์ VPN ได้สร้างการเชื่อมต่อไปยังเซิร์ฟเวอร์ของตนแล้วก็ยังสามารถกำหนดเส้นทางการเชื่อมต่อไปยังเว็บไซต์ที่ระบุได้เช่น example.org นอก VPN แต่แอปพลิเคชันทั้งหมดที่พยายามเข้าถึงที่อยู่พิเศษนั้นจะถูกกำหนดเส้นทางภายนอก VPN: คุณไม่สามารถมีบางแอปพลิเคชันที่จะไปที่ example.org ผ่าน VPN ในขณะที่แอปอื่น ๆ ส่งผ่านภายนอก VPN

สถานการณ์ยิ่งสมบูรณ์ยิ่งขึ้นด้วยเคอร์เนล Linux ซึ่งอนุญาตให้เราต์ซอร์ส: หมายความว่าคุณสามารถมีตารางการเราต์ได้สองตารางขึ้นไปและตัวเลือกระหว่างมันจะขึ้นอยู่กับที่อยู่ต้นทางไม่ใช่ที่อยู่ปลายทาง

ตัวอย่างที่ไม่สำคัญ: พีซีของฉันมีสองบรรทัดภายนอกที่มีสอง IP สาธารณะที่แตกต่างกัน สามารถติดต่อผ่านทางอินเทอร์เฟซทั้งสองและเป็นสิ่งสำคัญที่การตอบกลับของฉันไปยังการเชื่อมต่อที่กำหนดให้ผ่านอินเทอร์เฟซเดียวกับที่การเชื่อมต่อมาถึง: มิฉะนั้นพวกเขาจะถูกยกเลิก นี่คือการกำหนดเส้นทางต้นทาง

เป็นธรรมพอแล้วการเชื่อมต่อที่เราเริ่มต้นล่ะ แอพบางตัวอนุญาตให้คุณระบุที่อยู่ผูกเช่นไคลเอนต์ openssh :

-b bind_address

ใช้ bind_address บนเครื่องโลคัลเป็นที่อยู่ต้นทางของการเชื่อมต่อ มีประโยชน์เฉพาะกับระบบที่มีที่อยู่มากกว่าหนึ่งแห่ง

สำหรับพวกเขาไม่มีปัญหาในการมีหนึ่งอินสแตนซ์ที่จะผ่าน VPN (เช่นตารางเส้นทาง 1) ในขณะที่อินสแตนซ์อื่นจะออกนอก VPN (พูดว่าเส้นทางตาราง 2) แต่แอปอื่น ๆ เช่น Firefox ไม่เพียง แต่จะยากที่จะผูกกับที่อยู่ IP ของแหล่งที่มา (แต่ดูที่นี่เพื่อหาวิธีแก้ปัญหาที่ชาญฉลาดมาก) แต่ยังมีค่าเฉลี่ยและน่ารังเกียจที่พวกเขาจะไม่อนุญาตให้คุณมีสำเนาสองชุด ทำงานพร้อมกันแต่ละรายการเชื่อมโยงกับที่อยู่แหล่งข้อมูลที่แตกต่างกัน กล่าวอีกนัยหนึ่งด้วยเคล็ดลับที่อ้างถึงข้างต้นคุณสามารถบังคับหนึ่งอินสแตนซ์เพื่อผูกกับที่อยู่ต้นทางที่คุณเลือกได้จากนั้นคุณจะไม่สามารถผูกรุ่นอื่นกับที่อยู่ต้นทางอื่นได้

สิ่งนี้อธิบายว่าทำไมเราจึงใช้วิธีการแก้ไขปัญหา: ทั้งหมดนั้นใช้แนวคิดเดียวกันกับที่ทำงานกับเครือข่ายสแต็กแยกต่างหากจากส่วนที่เหลือของพีซี ดังนั้นคุณสามารถลดลำดับความซับซ้อนโดยประมาณ, VMs, นักเทียบท่า, คอนเทนเนอร์, เนมสเปซ ในแต่ละตารางคุณจะมีตารางเส้นทางหนึ่งตารางขึ้นไป แต่คุณสามารถมีหลายอินสแตนซ์ของแต่ละตัว (VM / dockers / container / namespaces) และคุณยังสามารถเพิ่มพวกมันได้อย่างอิสระแต่ละตัวทำงานแอพของตัวเองเช่น Firefox จากคนอื่น ๆ

บางทีคุณยังสนใจวิธีการแก้ปัญหาข้อใดข้อหนึ่งใช่หรือไม่

แก้ไข:

การหลีกเลี่ยงปัญหาที่ง่ายที่สุดคือเนมสเปซเครือข่าย สคริปต์ด้านล่างจัดการด้านที่จำเป็นทั้งหมดของ NNS: ใส่ไว้ในไฟล์ (คุณเลือกชื่อของคุณโดยทั่วไปฉันใช้newnsแต่คุณทำสิ่งที่คุณต้องการ) ใน/usr/local/binแล้วchmod 755 FILE_NAMEคุณสามารถใช้มันได้ดังนี้:

       newns NAMESPACE_NAME start
       newns NAMESPACE_NAME stop

มันจะเปิดxtermให้คุณ (นั่นเป็นเพราะฉันชอบ xterm ให้ทำงาน แต่คุณสามารถเปลี่ยนได้ถ้าคุณต้องการใช้อย่างอื่น) ซึ่งเป็นของเนมสเปซใหม่ จากภายใน xterm คุณสามารถเริ่ม vpn ของคุณแล้วเริ่มเกม คุณสามารถตรวจสอบได้อย่างง่ายดายว่าคุณใช้ VPN ผ่านคำสั่งต่อไปนี้:

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

ซึ่งจะให้ผลตอบแทน IP สาธารณะแก่คุณ หลังจากตั้งค่า VPN ใน xterm คุณอาจตรวจสอบว่า IP สาธารณะของคุณแตกต่างในหน้าต่างอื่นของคุณหรือไม่ คุณสามารถเปิดได้ถึง 254 xterms โดยมี NNSes 254 ที่แตกต่างกันและการเชื่อมต่อที่แตกต่างกัน

#!/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

หากคุณต้องการคุณสามารถเริ่มเดสก์ท็อปทั้งหมดภายในเนมสเปซเครือข่ายใหม่ได้

            sudo startx -- :2 

จากนั้นคุณสามารถค้นหาโดยใช้Alt+ Ctrl+ Fnโดยที่ Fn เป็นหนึ่งใน F1, F2, ....-

ฉันต้องเพิ่มหนึ่ง caveat: การจัดการ DNS ภายในเนมสเปซนั้นค่อนข้างลำบากใจเย็น ๆ


และในที่สุดฉันก็มีคำอธิบายที่เรียบง่าย แต่มีรายละเอียดว่าทำไมสิ่งที่ฉันพยายามทำสำเร็จไม่ใช่เรื่องง่ายและไม่ธรรมดา! ขอบคุณ! เมื่ออ่านสิ่งนี้ฉันเชื่อว่าวิธีแก้ปัญหาจะเหมาะสมเนื่องจากเป็นเพียงปริมาณการใช้งานจากโปรแกรมเฉพาะที่ฉันต้องการกำหนดเส้นทางและฉันต้องการให้โปรแกรมส่งเส้นทางนั้นเสมอ ตัวอย่าง: ฉันต้องการให้ VideoGameA ถูกส่งผ่าน VPN แต่ฉันไม่ต้องการให้โปรแกรมอื่น ๆ ส่งผ่านมัน มีวิธีง่าย ๆ ในการผูกพอร์ตเฉพาะเพื่อทำผ่านอินเตอร์เฟส VPN หรือไม่? ถ้าเป็นเช่นนั้นฉันจะตั้งค่าและเชื่อมต่อกับอินเทอร์เฟซดังกล่าวได้อย่างไร?
Josh Raymond

@JoshRaymond ตกลง ในการเลือกวิธีแก้ปัญหาที่ง่ายที่สุดคุณควรให้ตารางเส้นทางของคุณโพสต์ด้วย VPN และควรบอกฉันว่า VideoGameA ใช้พอร์ต UDP เลยหรือไม่
MariusMatutiae

มันใช้ทั้งพอร์ต TCP และ UDP 443, 3724 และ 1119 Route จะโพสต์ในการยกย่องต่อไป
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

ฉันสงสัยว่าทำไมในคำตอบ @MariusMatutiae สร้างการแตะและสะพาน? ดูเหมือนว่าจะทำงานได้ดีเพียงแค่ใช้อุปกรณ์สัตวแพทย์
Ian Kelling
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.