This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
unix:gateway [2013/10/13 12:32] robm [IP Forwarding and NAT] |
unix:gateway [2018/10/04 14:37] (current) robm Update link to Knoppix |
||
|---|---|---|---|
| Line 293: | Line 293: | ||
| I used to use Ubuntu' | I used to use Ubuntu' | ||
| - | < | + | See my ADSL project on GitHub: https:// |
| - | #!/bin/sh | + | |
| + | < | ||
| + | #!/bin/bash -e | ||
| # Adapted from http:// | # Adapted from http:// | ||
| + | DEV=$1 | ||
| DOWNLINK=$2 | DOWNLINK=$2 | ||
| UPLINK=$3 | UPLINK=$3 | ||
| - | DEV=$1 | + | |
| + | # The following fudge factors allow you to express the usable % of your link. | ||
| + | # | ||
| + | # Experimentation has shown that ~75% of the author' | ||
| + | # before upstream congestion starts to affect round-trip times. In other words, | ||
| + | # by throttling our download speeds we can ensure that our ISP does not queue | ||
| + | # any packs on our behalf, giving us full control over congestion. | ||
| + | DOWNFACTOR=' | ||
| + | UPFACTOR=' | ||
| if [ " | if [ " | ||
| then | then | ||
| - | echo " | + | echo " |
| exit 0 | exit 0 | ||
| fi | fi | ||
| Line 311: | Line 322: | ||
| if [ " | if [ " | ||
| then | then | ||
| - | tc -s qdisc ls dev $DEV | + | |
| + | #iptables -nvL -t mangle | ||
| + | #echo " | ||
| + | tc -s filter ls dev $DEV | ||
| + | echo " | ||
| + | #tc -s qdisc ls dev $DEV | ||
| + | #echo " | ||
| tc -s class ls dev $DEV | tc -s class ls dev $DEV | ||
| exit 0 | exit 0 | ||
| Line 319: | Line 336: | ||
| tc qdisc del dev $DEV root 2> /dev/null > /dev/null || true | tc qdisc del dev $DEV root 2> /dev/null > /dev/null || true | ||
| tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null || true | tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null || true | ||
| + | |||
| + | # Flush and delete all mangle rules | ||
| + | iptables -F | ||
| + | iptables -X | ||
| + | iptables -t mangle -F | ||
| + | iptables -t mangle -X | ||
| if [ " | if [ " | ||
| Line 326: | Line 349: | ||
| fi | fi | ||
| - | ############################################################################### | + | trap "$0 $1 clear" ERR |
| - | # UPLINK | + | |
| - | # Set root Queuing Discipline (qdisc) | + | # Calculations |
| - | tc qdisc add dev $DEV root handle | + | # |
| + | # Target latency is < 50ms. This means max burst length should be limited | ||
| + | # 1/20th the queue' | ||
| - | # Traffic is either headed to the gateway (i.e. internet traffic) or not. | ||
| - | # Internet uplink is scarse, so aggresively shape it. LAN uplink is plentiful, | ||
| - | # do not restrict it. | ||
| + | LOCALIP=$(ifconfig eth0 | sed -ne ' | ||
| + | |||
| + | # ============================================================================= | ||
| + | # Queues and Classes | ||
| # ============================================================================= | # ============================================================================= | ||
| - | # INTERNET GATEWAY: Shape to $UPLINK speed, | + | # 1: ROOT |
| - | # DSL modem that cause massive latency | + | # |-- 1:ff LOCAL_TRAFFIC (to/from this host itself) |
| - | tc class add dev $DEV parent | + | # | `-- ff: (sfq) |
| - | allot 1500 prio 5 bounded isolated | + | # |-- 1:1 INTERNET-> |
| + | # | `-- 10: (red) Drop traffic as link approaches congestion | ||
| + | # `-- 1:2 LAN-> | ||
| + | # |-- 1:21: High priority | ||
| + | # | `-- 21: (sfq) | ||
| + | # |-- 1:22: Medium priority | ||
| + | # | `-- 22: (sfq) | ||
| + | # `-- 1:23: Low priority | ||
| + | # `-- 23: (sfq) Low priority | ||
| - | # High priority internet traffic | + | # ROOT |
| - | tc class add dev $DEV parent 1:1 classid 1:10 cbq rate ${UPLINK}kbit \ | + | tc qdisc add dev $DEV root handle |
| - | allot 1600 prio 1 avpkt 1000 | + | |
| - | # .. and its actual queue that holds the packets | + | |
| - | tc qdisc add dev $DEV parent | + | |
| + | # LOCAL TRAFFIC | ||
| + | tc class add dev $DEV parent 1: classid 1:ff htb \ | ||
| + | rate 100mbit \ | ||
| + | burst $((100/ | ||
| + | cburst $((100/ | ||
| + | prio 1 | ||
| - | # Default priority internet traffic, bulk transfers. | + | |
| - | tc class add dev $DEV parent 1:1 classid 1:20 cbq rate $((9*$UPLINK/ | + | tc qdisc add dev $DEV parent 1:ff handle |
| - | allot 1600 prio 2 avpkt 1000 | + | |
| - | # .. and its actual queue that holds the packets | + | |
| - | tc qdisc add dev $DEV parent 1:20 handle | + | |
| - | # Low priority traffic. | + | |
| - | tc class add dev $DEV parent 1:1 classid 1:30 cbq rate $((8*$UPLINK/10))kbit \ | + | tc class add dev $DEV parent 1: classid 1:1 htb \ |
| - | allot 1600 prio 2 avpkt 1000 | + | |
| - | # .. and its actual queue that holds the packets | + | ceil $(($DOWNLINK*$DOWNFACTOR))kbit \ |
| - | tc qdisc add dev $DEV parent 1:30 handle 30: sfq perturb | + | burst $(($DOWNLINK*$DOWNFACTOR/ |
| + | | ||
| + | prio 10 | ||
| - | # ============================================================================= | + | |
| - | # LAN | + | # Note: All values are in BYTES. It doesn' |
| - | tc class add dev $DEV parent 1: classid | + | # |
| - | | + | # The burst calculation needs to be increased by one so as to avoid an |
| - | tc qdisc add dev $DEV parent | + | # internal assert in the qdisc (seems our target and their min |
| + | # acceptable burst are one and the same) | ||
| + | | ||
| + | limit $(($DOWNLINK*$DOWNFACTOR*1000/ | ||
| + | avpkt 1500 \ | ||
| + | | ||
| + | min | ||
| + | max | ||
| + | ecn \ | ||
| + | probability | ||
| - | # ============================================================================= | + | |
| - | # Filters | + | tc class add dev $DEV parent 1: classid 1:2 htb \ |
| + | rate $(($UPLINK*$UPFACTOR))kbit \ | ||
| + | ceil $(($UPLINK*$UPFACTOR))kbit \ | ||
| + | burst $(($UPLINK/ | ||
| + | cburst $(($UPLINK/ | ||
| + | prio 20 | ||
| - | # LAN traffic ----------------------------------------------------------------- | + | |
| - | tc filter | + | tc class add dev $DEV parent 1:2 classid |
| - | match ip dst 192.168.0.0/16 flowid 1:40 | + | rate $(($UPLINK*$UPFACTOR*4/6))kbit \ |
| - | tc filter add dev $DEV parent 1:0 protocol ip prio 1 u32 \ | + | |
| - | match ip dst 10.0.0.0/8 flowid 1:40 | + | prio 0 |
| - | tc filter add dev $DEV parent 1:0 protocol ip prio 1 u32 \ | + | |
| - | match ip dst 172.16.0.0/12 flowid 1:40 | + | |
| - | # Internet traffic ------------------------------------------------------------ | + | |
| + | tc class add dev $DEV parent 1:2 classid 1:22 htb \ | ||
| + | rate $(($UPLINK*$UPFACTOR*2/ | ||
| + | ceil $(($UPLINK*$UPFACTOR))kbit \ | ||
| + | prio 1 | ||
| - | # TOS Minimum Delay (ssh, NOT scp) in 1:10: | + | |
| - | tc filter | + | tc class add dev $DEV parent 1:2 classid 1:23 htb \ |
| - | match ip tos 0x10 0xff flowid | + | rate $(($UPLINK*$UPFACTOR*1/6))kbit \ |
| + | prio 2 | ||
| - | # ICMP (ip protocol 1) in the interactive class 1:10 so we | + | |
| - | # can do measurements & impress our friends: | + | for ID in 21 22 23 |
| - | tc filter | + | |
| - | match ip protocol | + | tc qdisc add dev $DEV parent 1:$ID handle $ID: sfq |
| + | ## | ||
| + | ## | ||
| + | ## avpkt 1500 \ | ||
| + | ## burst $((($UPLINK*1000/ | ||
| + | ## | ||
| + | ## | ||
| + | ## ecn \ | ||
| + | ## | ||
| + | done | ||
| - | # pablo.iranzo@uv.es provided a patch for the MLDonkey system | ||
| - | # The MLDonkey uses small UDP packets for source propogation | ||
| - | # which floods the wondershaper out. | ||
| - | tc filter add dev $DEV parent 1:0 protocol ip prio 10 u32 \ | ||
| - | match ip protocol 17 0xff \ | ||
| - | match ip sport 4666 0xffff \ | ||
| - | | ||
| - | # prioritize small packets (<64 bytes) | + | # ============================================================================= |
| + | # Filters | ||
| + | # ============================================================================= | ||
| - | tc filter add dev $DEV parent 1: protocol ip prio 12 u32 \ | + | # ----------------------------------------------------------------------------- |
| - | match ip protocol 6 0xff \ | + | # LOCAL TRAFFIC |
| - | match u8 0x05 0x0f at 0 \ | + | # Mark traffic generated by this host itself (INPUT + OUTPUT, but not FORWARD) |
| - | match u16 0x0000 0xffc0 at 2 \ | + | iptables -t mangle -A INPUT -p all -i $DEV -j MARK --set-mark |
| - | | + | iptables -t mangle -A OUTPUT -p all -o $DEV -j MARK --set-mark 0xff |
| + | # (" | ||
| + | tc filter add dev $DEV parent 1: protocol ip prio 1 handle 0xff fw classid 1:ff | ||
| - | #for a in $NOPRIOPORTDST | + | # ----------------------------------------------------------------------------- |
| - | #do | + | # INTERNET-> |
| - | # tc filter add dev $DEV parent 1: protocol ip prio 14 u32 \ | + | |
| - | # match ip dport $a 0xffff flowid 1:30 | + | |
| - | #done | + | |
| # | # | ||
| - | #for a in $NOPRIOPORTSRC | + | # Note: We assume that LAN->LAN traffic is *not* forwarded through this host, |
| - | #do | + | # and so we need only check the destination of a given packet. We've already |
| - | # tc filter add dev $DEV parent 1: protocol ip prio 15 u32 \ | + | # taken care of this host's own traffic above. |
| - | # match ip sport $a 0xffff flowid 1:30 | + | |
| - | #done | + | iptables -t mangle -N DOWNLINK |
| + | iptables -t mangle -A DOWNLINK -p all -j MARK --set-mark 0x1 | ||
| + | tc filter add dev $DEV parent 1: protocol ip prio 2 handle 0x1 fw classid 1:1 | ||
| + | |||
| + | for SUBNET in 192.168.0.0/ | ||
| + | do | ||
| + | | ||
| + | done | ||
| + | |||
| + | |||
| + | # ----------------------------------------------------------------------------- | ||
| + | # LAN-> | ||
| # | # | ||
| - | #for a in $NOPRIOHOSTSRC | + | # Note: Assumes that all downlink and private traffic have already been |
| - | #do | + | # classified, so no source checks are performed. |
| - | # tc filter add dev $DEV parent 1: protocol ip prio 16 u32 \ | + | |
| - | # match ip src $a flowid 1:30 | + | iptables -t mangle -N UPLINK |
| - | #done | + | iptables -t mangle -A UPLINK -p all -j MARK --set-mark 0x22 # Default to medium priority |
| - | # | + | #for CHAIN in PREROUTING INPUT FORWARD OUTPUT POSTROUTING DOWNLINK UPLINK |
| - | #for a in $NOPRIOHOSTDST | + | |
| #do | #do | ||
| - | # tc filter add dev $DEV parent 1: protocol ip prio 17 u32 \ | + | # |
| - | # match ip dst $a flowid 1:30 | + | # |
| #done | #done | ||
| - | # Internet traffic catch-all: bulk. | + | for SUBNET in 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 |
| - | tc filter add dev $DEV parent 1: protocol ip prio 18 u32 \ | + | do |
| - | match ip dst 0.0.0.0/ | + | iptables -t mangle -A PREROUTING -p all -i $DEV -s $SUBNET ! -d $SUBNET -j UPLINK |
| + | done | ||
| + | ## | ||
| + | ## HIGH PRIORITY ## | ||
| + | ## | ||
| - | ############################################################################### | + | # TOS Minimum Delay (ssh, NOT scp) |
| - | # DOWNLINK | + | tc filter add dev $DEV parent 1: protocol ip prio 20 u32 \ |
| - | # | + | match ip tos 0x10 0xff \ |
| - | # Limit downloads to slightly less than the maximum achievable speed. This | + | |
| - | # prevents a queues building up in the ISP (which is typically a huge FIFO), | + | |
| - | # and so reduces round-trip time; effectively reducing latency. | + | |
| - | # Ingress policer | + | # ICMP (ip protocol 1) in the interactive class so we can do measurements & |
| - | # (FYI: The term " | + | # impress our friends: |
| - | # ingress equivalent) | + | tc filter add dev $DEV parent 1: protocol ip prio 20 u32 \ |
| + | match ip protocol 1 0xff \ | ||
| + | flowid 1:21 | ||
| - | tc qdisc add dev $DEV handle ffff: ingress | + | # Prioritize small packets (<64 bytes) |
| + | tc filter | ||
| + | match ip protocol 6 0xff \ | ||
| + | match u8 0x05 0x0f at 0 \ | ||
| + | match u16 0x0000 0xffc0 at 2 \ | ||
| + | flowid 1:21 | ||
| - | # LAN traffic is exempt from policing | + | # Prioritise ACK packets (but only if they are small) |
| - | tc filter add dev $DEV parent ffff: protocol | + | # IP protocol |
| - | match ip src 192.168.0.0/ | + | # IP header length 0x5(32 bit words), |
| - | | + | # IP Total length 0x34 (ACK + 12 bytes of TCP options) |
| - | | + | # TCP ack set (bit 5, offset 33) |
| - | tc filter add dev $DEV parent | + | tc filter add dev $DEV parent |
| - | match ip src 10.0.0.0/ | + | match ip protocol 6 0xff \ |
| - | | + | |
| - | | + | |
| - | tc filter add dev $DEV parent ffff: protocol ip prio 40 u32 \ | + | match u8 0x10 0xff at 33 \ |
| - | match ip src 172.16.0.0/ | + | flowid |
| - | police pass \ | + | |
| - | flowid :1 | + | |
| - | # Internet traffic that arrives too fast should be discarded | + | # Traffic headed to robmeerman.co.uk (typically SSH proxying to else where) |
| - | tc filter add dev $DEV parent | + | tc filter add dev $DEV parent |
| - | match ip src 0.0.0.0/0 \ | + | match ip dst 85.119.82.218/32 \ |
| - | police rate ${DOWNLINK}kbit burst 10k drop \ | + | flowid |
| - | flowid :1 | + | |
| - | </ | + | |
| + | # Traffic originating from the Xbox should be treated as urgent | ||
| + | tc filter add dev $DEV parent 1: protocol ip prio 20 u32 \ | ||
| + | match ip src 192.168.1.2/ | ||
| + | flowid 1:21 | ||
| + | |||
| + | |||
| + | ## | ||
| + | ## LOW PRIORITY ## | ||
| + | ## | ||
| + | |||
| + | # # WiiU, while it's downloading purchases | ||
| + | # tc filter add dev $DEV parent 1: protocol ip prio 30 u32 \ | ||
| + | # match ip src 192.168.1.5/ | ||
| + | # | ||
| + | |||
| + | # TOS High Throughput | ||
| + | tc filter add dev $DEV parent 1: protocol ip prio 30 u32 \ | ||
| + | match ip tos 0x8 0xff \ | ||
| + | flowid 1:23 | ||
| + | |||
| + | # If no other filter has classified the packet, then use FW markers (set by | ||
| + | # iptables -j MARK). All UPLINK packets are marked as 0x22 by default (see | ||
| + | # iptables command earlier) | ||
| + | tc filter add dev $DEV parent 1: protocol ip prio 40 handle 0x21 fw classid 1:21 # High priority | ||
| + | tc filter add dev $DEV parent 1: protocol ip prio 40 handle 0x22 fw classid 1:22 # Medium priority | ||
| + | tc filter add dev $DEV parent 1: protocol ip prio 40 handle 0x23 fw classid 1:23 # Low priority | ||
| + | |||
| + | |||
| + | # Reset counters, so that packet counts are in sync (it takes time to add | ||
| + | # rules, and during that time the first rule added may be hit, leading to | ||
| + | # confusing packet counts: "But these rules should always apply to the same | ||
| + | # packets! How can their hit count be different?" | ||
| + | iptables -t mangle -Z | ||
| + | </ | ||
| ==== Transparent Web Proxy ==== | ==== Transparent Web Proxy ==== | ||
| Line 485: | Line 589: | ||
| ==== My Solution ==== | ==== My Solution ==== | ||
| - | I use WinXP on my laptop, and happened to have a copy of [[http:// | + | I use WinXP on my laptop, and happened to have a copy of [[http:// |
| Amazingly, this worked! I had 3 IPs on one NIC: 2 for the virtual machine running Knoppix, and 1 for Windows itself. Actually, IIRC, all 3 actually had seperate MAC addresses too. | Amazingly, this worked! I had 3 IPs on one NIC: 2 for the virtual machine running Knoppix, and 1 for Windows itself. Actually, IIRC, all 3 actually had seperate MAC addresses too. | ||