iptables - set-mark - กำหนดเส้นทางพอร์ตที่แตกต่างกันผ่านส่วนต่อประสานที่แตกต่างกัน


15

เรื่องสั้น
3 อินเตอร์เฟส, eth0 (LAN), eth1 (ADSL), eth2 (4G)
eth0 -> eth1: ทำงาน
(พอร์ต 80, 443, 4070) eth0 -> eth2: ไม่เกิดขึ้น


นี่คือการแสดงกราฟิกของความคิด:

พอร์ต 80 และ 443 ผ่าน eth2
ant ส่วนที่เหลือผ่าน eth1
ป้อนคำอธิบายรูปภาพที่นี่

Netscheme:

eth0: -ip 10.0.0.1 -net 10.0.0.0/8 -gw 10.0.0.1 (the servers own intf) 
eth1: -ip 192.168.1.74 -net 192.168.1.0/24 -gw 192.168.1.254 
eth2: -ip 192.168.1.91 -net 192.168.0.0/24 -gw 192.168.0.1 






สคริปต์ใหม่นี้เปลี่ยนเส้นทาง 22 และ 4070 ไปยังตารางที่เหมาะสมฉันคิดว่า
อย่างไรก็ตามหลังจากไปที่ตารางนั้นจะไม่ได้รับการเปลี่ยนเส้นทางเป็น eth2




สคริปต์นี้ใช้งานได้ยกเว้น 22 และ 4070!

(พอร์ต 80 ยกเลิกการใส่ความคิดเห็นและใช้งานได้ แต่ผ่าน eth1 ซึ่งผิด)

modprobe iptable_nat
modprobe ip_conntrack

echo "1" > /proc/sys/net/ipv4/ip_forward

iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -F PREROUTING
iptables -t nat -F
iptables -t mangle -F
iptables -F
# This next line restores any issues trying to connect to something
# if you get weird ACK packets when trying to connect (at least i did)!
iptables -t mangle -A PREROUTING -p tcp -j CONNMARK --restore-mark
ip route flush table main

iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 22 -j MARK --set-mark 1
###  iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 80 -j MARK --set-mark 1
iptables -A PREROUTING -i eth0 -t mangle -p tcp --dport 4070 -j MARK --set-mark 1

## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
## -- Does the same as ip route below? route add default gw 192.168.1.254


echo "201 eth2.out" >> /etc/iproute2/rt_tables

ip rule add fwmark 1 table eth2.out
ip route add default via 192.168.0.1 dev eth2 table eth2.out
ip route add default via 192.168.1.254 dev eth1



## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE









สคริปต์เก่า:


  Ignore everything below unless you're interested in retracing my steps!!




ฉันสร้างสคริปต์ router.sh เพื่อตั้งค่าสภาพแวดล้อมของฉันในกรณีที่ฉันทำสิ่งที่ไม่ดี ฉันมี 3 พอร์ตที่ฉันต้องการส่งไปยังการเชื่อมต่อ 4G และส่วนที่เหลือผ่านการเชื่อมต่อ ADSL พื้นฐาน ในการทำเช่นนี้ฉันได้สั่ง iptables ให้ทำการแพกเกจแพ็กเกจบนเส้นทางเริ่มต้นและส่งผ่านอินเทอร์เฟซ 4G ของฉันถ้า --dport == 443 | 80 | 4070

อย่างไรก็ตามสิ่งนี้ไม่ได้ผล ฉันยังคงถูกส่งผ่านโทรศัพท์พื้นฐานของฉันไม่ว่าจะเกิดอะไรขึ้น

นี่คือลักษณะของสคริปต์ของฉัน:

#!/bin/bash

## routing tables
# wireless = 4G via eth2
# adsl = adsl via eth1

modprobe iptable_nat
modprobe ip_conntrack

echo "1" > /proc/sys/net/ipv4/ip_forward

iptables -P INPUT ACCEPT
iptables -F INPUT
iptables -P OUTPUT ACCEPT
iptables -F OUTPUT
iptables -P FORWARD DROP
iptables -F FORWARD
iptables -t nat -F
ip route flush table main
ip route flush table wireless
ip route flush table adsl

## Setup routing tables
# ADSL
ip route add table adsl to 192.168.1.0/24 dev eth1
# 4G
ip route add table wireless to 192.168.0.0 dev eth2
ip rule add fwmark 0x1 table wireless

## Setup routes
# LAN
route add -net 10.0.0.0 netmask 255.0.0.0 dev eth0
# ADSL
route add -net 192.168.1.0 netmask 255.255.255.0 dev eth1
# 4G (Only accessible if marking packages with \x01
route add -net 192.168.0.0 netmask 255.255.255.0 dev eth2
# Default via ADSL
route add default gw 192.168.1.254


## Forward ports into the LAN
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.0.3:80


## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A OUTPUT -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1

## Setup forwards
# From 4G to LAN
iptables -A FORWARD -i eth2 -o eth0 -m state --state ESTABLISHED,RELATED,NEW -j ACCEPT
# From ADSL to LAN
iptables -A FORWARD -i eth1 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
# From LAN to ADSL (Default route out)
# - Note: If marked packages is sent to ADSL they will be mangled and rerouted to 4G
iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
iptables -A FORWARD -j LOG
#iptables --table nat --append POSTROUTING --out-interface eth2 --jump SNAT --to-source "192.168.1.74"
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

ฉันยังพยายามเพิ่ม 3 เหล่านี้ไปยังด้านล่างของสคริปต์:

iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 80 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 443 -j SNAT --to "192.168.0.91"
iptables -t nat -A POSTROUTING -o eth2 -p tcp --dport 4070 -j SNAT --to "192.168.0.91"

ยังพยายามไม่สำเร็จ:

iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 1

สุดท้าย แต่ไม่ท้ายสุดพยายาม:

## Lets mark all packets we want for 4G forward
# HTTPS
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 443 -j MARK --set-mark 1
# HTTP
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 80 -j MARK --set-mark 1
# Spotify
iptables -A POSTROUTING -t mangle -o eth1 -p tcp --dport 4070 -j MARK --set-mark 1

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

ฉันเดาว่าฉันกำลังทำผิดกับกฎที่แตกต่างกันส่วนใหญ่เป็นส่วนMASQUERADE ? หรือว่าควรจะมี?

ใครสามารถอธิบายวิธีการDNATพอร์ตพูด tcp: 80 จากอินเทอร์เฟซภายนอก (โพรโทคอลหนึ่งหรือทั้งสอง) ไปยังพื้นที่ที่อยู่ 10.0.0.0 ภายในหรือไม่



ขาออก:

root@Netbridge:~# route -n Kernel IP routing table Destination    

Gateway         Genmask         Flags Metric Ref    Use Iface<br>
0.0.0.0         192.168.1.254   0.0.0.0         UG    0      0        0 eth1<br>
10.0.0.0        0.0.0.0         255.0.0.0       U     0      0        0 eth0<br>
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 eth2<br>
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1


root@Netbridge:~# ifconfig

eth0      Link encap:Ethernet  HWaddr 00:0c:29:7e:9e:4e  
          inet addr:10.0.0.1  Bcast:10.255.255.255  Mask:255.0.0.0

eth1      Link encap:Ethernet  HWaddr 00:0c:29:7e:9e:58  
          inet addr:192.168.1.74  Bcast:192.168.1.255  Mask:255.255.255.0

eth2      Link encap:Ethernet  HWaddr 00:0c:29:7e:9e:62  
          inet addr:192.168.0.91  Bcast:192.168.0.255  Mask:255.255.255.0

ทำตามคำแนะนำเหล่านี้:
เอาท์พุทปริมาณการใช้งานบนที่แตกต่างกันอินเทอร์เฟซบนปลายทางปลายทาง por
iptables ไปข้างหน้าเฉพาะพอร์ตไปยังเฉพาะนิก
ในบรรดาหัวข้ออื่น ๆ ที่เกี่ยวข้อง


ฉันขอโทษ แต่มีเหตุผลที่จะไม่ผูกอาปาเช่กับที่อยู่localhostและที่อยู่ของeth2อินเทอร์เฟซเท่านั้นหรือไม่
Jan Marek

@JanMarek: ไม่มีการพูดถึง apache ที่นี่ และสำหรับข้อมูลของคุณการผูกซ็อกเก็ตที่อยู่ethXIP ของจะป้องกันโฮสต์บนethXLAN เพื่อเข้าถึงเซิร์ฟเวอร์ท้องถิ่นโดยใช้ethYที่อยู่ IP ของและจะไม่ป้องกันโฮสต์จากการethYเข้าถึงเซิร์ฟเวอร์โดยใช้ethXที่อยู่ IP ของ โปรดจำไว้ว่า Linux ใช้โมเดลโฮสต์ที่อ่อนแอ
BatchyX

ตกลงมีเว็บเซิร์ฟเวอร์ที่เป็นไปได้มากขึ้นไม่เพียง แต่เซิร์ฟเวอร์ apache ... ฉันว่าการผูกเว็บเซิร์ฟเวอร์บนอินเตอร์เฟส eth2 อาจเป็นวิธีแก้ปัญหาที่ง่าย แต่ฉันอาจผิดฉันรู้
Jan Marek

คำตอบ:


6

BatchyX ให้คำอธิบายที่ดีมากเกี่ยวกับ iptables และการกำหนดเส้นทางดังนั้นฉันจะออกกำลังกายด้วยความเกียจคร้านและไปที่สคริปต์โดยตรง

ควรรับส่งข้อมูลทั้งหมดไปยังพอร์ต 80,443,22,4070 ถึง 192.168.0.91 ที่เหลือทั้งหมดจะ NAT ผ่าน 192.168.1.254

ฉันทำการทดสอบอีกครั้งและจบการติดตามคู่มือนี้ สิ่งที่ขาดหายไปในคู่มือนั้นคือ 3 บรรทัดสุดท้ายในสคริปต์ของฉัน ซึ่งฉันค้นพบจากพอร์ตอื่น แต่ฉันสูญเสียการติดตามลิงก์นั้น

มันเป็นสคริปต์การทำงานที่ทดสอบแล้ว

ต้องการเส้นทางเริ่มต้น

สิ่งหนึ่งที่ฉันไม่ได้ใส่ในสคริปต์คือการตั้งค่าเส้นทางเริ่มต้น มันควรจะเป็น

route add default gw 192.168.1.254

เมื่อคุณทำroute -nมันควรเป็นเส้นทางเริ่มต้นเท่านั้น (ปลายทาง: 0.0.0.0)

0.0.0.0    192.168.1.254    0.0.0.0    UG    0    0    0    eth1

fw-router.sh

# รีเซ็ต / ล้าง iptables
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P ยอมรับการยอมรับ
iptables -P ไปข้างหน้ายอมรับ
iptables -P ยอมรับผลลัพธ์

# รีเซ็ต / ล้าง / ตั้งค่าเส้นทาง IP (ตารางที่ 4)
เส้นทาง ip flush ตารางที่ 4
ip แสดงเส้นทางตารางหลัก | grep -Ev ^ default | ในขณะที่อ่าน ROUTE ทำเส้นทาง ip เพิ่มตาราง 4 $ ROUTE; เสร็จแล้ว
เส้นทาง ip เพิ่มตาราง 4 เริ่มต้นผ่าน 192.168.0.1

#Mark Packet พร้อมการจับคู่ D.Port
iptables -t mangle -A การประมวลผล -p tcp --dport 22 -s 10.0.0.0/24 -j เครื่องหมาย - set-mark 4
iptables -t mangle -A การประมวลผล -p tcp --dport 80 -s 10.0.0.0/24 -j เครื่องหมาย - set-mark 4
iptables -t mangle -A การประมวลผล -p tcp --dport 443 -s 10.0.0.0/24 -j MARK - set-mark 4
iptables -t mangle -A การประมวลผล -p tcp --dport 4070 -s 10.0.0.0/24 -j เครื่องหมาย - set-mark 4

#SNAT กฎ
iptables -t nat -A POSTROUTING -o eth1 -j SNAT - ไปยังแหล่ง 192.168.1.74
iptables -t nat -A การนำเสนอ -o eth2 -j SNAT - ไปยังแหล่ง 192.168.0.91

#IP เส้นทาง
กฎ ip เพิ่ม fwmark 4 ตาราง 4
ip ip flush flush แคช

#IP สแต็ค
# นี่คือส่วนที่ขาดไปจากคำแนะนำ
echo 1> / proc / sys / net / ipv4 / ip_forward
สำหรับ f ใน / proc / sys / net / ipv4 / conf / * / rp_filter; ทำเสียงสะท้อน 0> $ f; เสร็จแล้ว
echo 0> / proc / sys / net / ipv4 / route / flush

PS1:ในระยะสั้นMASQUERADEไม่ทำงาน (ในกรณีส่วนใหญ่และแน่นอนในกรณีของคุณ) สำหรับ NAT ที่มี IP ภายนอกหลายตัวที่ต้องการการปรับสมดุลโหลดบางประเภทหรือต้องการ DNAT เพื่อจัดการทราฟฟิกที่เข้ามา คุณต้องการSNATการควบคุมทิศทาง

PS2: iptables แท้ไม่เพียงพอ


ก่อนอื่นไชโยให้ไปที่สคริปต์โดยตรง :) ฉันจะลองคืนนี้เมื่อฉันกลับไปที่สภาพแวดล้อมที่สิ่งนี้จะทำงาน!
Torxed

อืมอาจต้องมีการแก้ไขอย่างมาก แจ้งให้เราทราบผล
John Siu

แก้ไขควรจะทำงานตอนนี้
John Siu

ที่รักจะกลับมาหาคุณในระยะเวลาอันสั้น: D
Torxed

ฉันรักคุณปวดหัวมากและคุณแก้ไขมันได้! ขอขอบคุณ!
Torxed

6

หมายเหตุ: ฉันเพิ่งพิจารณาสคริปต์แรกโดยไม่สนใจสคริปต์เก่า

  • คุณไม่จำเป็นต้องดัดแปลงโมดูล netfilter ด้วยตัวเองด้วย iptables ปัจจุบัน สิ่งนี้จำเป็นสำหรับเครื่องมือติดตามการเชื่อมต่อที่กำหนดเองเท่านั้น
  • อย่าผสมขึ้นและroute ip routeนี่คือความชั่วร้ายที่บริสุทธิ์ เพียงใช้ipทุกที่และลืมifconfigและroute
  • /etc/iproute2/rt_tablesไม่ได้ถูกรีเซ็ตข้ามการรีบูต การต่อท้ายรายการเดียวกันซ้ำไปซ้ำมาไม่ใช่ความคิดที่ดีคุณต้องทำเพียงครั้งเดียว โปรดจำไว้ว่าrt_tablesเพียงกำหนดชื่อแทนให้เป็นค่าตัวเลขจะไม่เปลี่ยนการกำหนดค่าใด ๆ

  • ตอนนี้สำหรับiptables: ในFORWARDห่วงโซ่ของคุณคุณวางแพ็กเก็ตจาก LAN เป็น 4G นี้ไม่ดี. ใช้FORWARDเบ็ดหลังจากกำหนดเส้นทางเสร็จแล้ว ณ จุดนี้การกำหนดเส้นทางนโยบายทั้งหมดเสร็จสิ้นและเป็นที่ทราบกันดีว่าควรส่งแพ็กเก็ตไปยัง 4G หรือ ADSL ไม่มีการกำหนดเส้นทางใหม่ในFORWARDหรือหลังจากนั้นFORWARD(ในทางเทคนิคการกำหนดเส้นทางใหม่สามารถทำได้หลังจากPOSTROUTINGในกรณีที่รุนแรง แต่กลับไปที่จุด)

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

สำหรับแพ็กเก็ตที่ได้รับจากeth0นี่ไม่ใช่ปัญหา สำหรับข้อมูลที่ได้รับจากeth1นี้ยังไม่เป็นปัญหาเพราะเมื่อย้อนกลับแหล่งที่อยู่ IP และที่อยู่ IP mainปลายทางเคอร์เนลมันจะเส้นทางเริ่มต้นในตาราง สำหรับข้อมูลที่ได้รับจากการeth2ที่คุณไม่ได้ทำเครื่องหมายนี้เป็นปัญหาเพราะเมล็ดจะตีเส้นทางเริ่มต้นในตารางและพิจารณาว่าแพ็คเก็ตเหล่านี้ควรจะได้รับการตอบรับจากmain eth1ทางออกที่ง่ายที่สุดคือการปิดการใช้งานการกรองเส้นทางย้อนกลับบน eth1:

sysctl -w net.ipv4.conf.eth1.rp_filter=0

ความเห็นที่ยอดเยี่ยมและใช่มีข้อผิดพลาดบางอย่างในส่วนของฉันตัวอย่างเช่นผนวกกับ rt_tables ทุกครั้งและโดยเฉพาะอย่างยิ่งไม่ได้ล้างตารางบางอย่างเช่นเดียวกับที่ฉันควร แต่ฉันจะไปที่นั่น :) ฉันจะให้ทุกอย่างไป ถ้ามันใช้งานได้ถ้าเป็นเช่นนั้นให้คุณ +50 และที่สำคัญคุณได้ช่วยคนไว้เบื้องหลังไม่ให้ถูกสับเป็นชิ้นเล็กชิ้นน้อย! :)
Torxed

1
สคริปต์ด้านล่างนี้ใช้งานได้ แต่คุณสมควรได้รับความกตัญญูเช่นกันคุณให้สิ่งหนึ่งหรือสองอย่างให้ฉันคิดและ rp_filter = 0 ช่วยนานมาก! : D
Torxed

@BatchyX ให้ข้อมูลอย่างมากโหวตให้คุณเช่นกัน
จอห์นซิว

@ Torxed โพสต์ที่ฉันเห็นพูดถึง rp_filter สำหรับอินเตอร์เฟสทั้งหมดจำเป็นต้องปิดการใช้งาน ฉันไม่แน่ใจว่าทำงานได้หรือไม่
จอห์นซิว

@JohnSiu: คุณเพียงแค่ปิดการใช้งานตัวกรอง rp บนอินเทอร์เฟซที่มีปัญหา ในกรณีนั้นมันคือ eth1 เนื่องจากไม่มีเส้นทางไปยังอินเตอร์เฟสนั้นเมื่อไม่ได้ตั้งเครื่องหมายไว้ eth2 ไม่มีปัญหาดังกล่าวเนื่องจากเส้นทางเริ่มต้นเข้าสู่ส่วนต่อประสานนั้น สำหรับ eth0 มันมีประโยชน์จริง ๆ ที่เปิดใช้งาน rp filter มิฉะนั้นใครบางคนบน LAN สามารถปลอมแปลงแพ็กเก็ต IP ที่มีแหล่งที่อยู่บนอินเทอร์เน็ตและที่อยู่ปลายทางบน LAN และเราเตอร์จะยอมรับมันอย่างมีความสุขและส่งต่อ มันกลับไปที่ ... eth0
BatchyX
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.