So, to be completely informed. We have router with 3 interfaces. First uplink is connected to eth0 interface, LAN network is connected to eth1 interface, and second uplink is connected to eth2. Public address of first uplink is 198.51.100.100/24, public address of second uplink is 203.0.113.100/24, and LAN side address is 192.168.0.1/24. LAN network addressing is 192.168.0.0/24.
Both uplinks are asymmetric with 8000kb/s downstream rate, 500kb/s upstream rate and 10000kb/s downstream rate, 600kb/s upstream rate.
There are many ways to use load balancing on two uplinks. In this scenario we use first uplink as default and second for http and e-mail traffic only. Both http and e-mail don't generate static traffic. Thanks to that, it's excellent to share uplink throughput between many hosts. Also using as high as possible of both downstream and upstream is a goal.
Let's execute command written below:
After executing this script, all of TCP packets with destination ports equal to one of these from isp2_ports_tcp will be marked with 0x2 value. Thanks to that, all of such packets will be routed by second uplink and NiceShaper will be able to recognize and control them by certain sections.
Below is script content to be pasted to your file. Remember to edit configuration section.
# === Configuration ===
wan1_iface="eth0"
wan1_net="198.51.100.0/24"
wan1_ip="198.51.100.100"
wan1_gw="198.51.100.2"
lan_iface="eth1"
lan_net="192.168.0.0/24"
wan2_iface="eth2"
wan2_net="203.0.113.0/24"
wan2_ip="203.0.113.100"
wan2_gw="203.0.113.2"
isp2_ports_tcp="80,443,25,465,143,993,110,995"
# === Operating System preparation ===
IP=`which ip`
IPT=`which iptables`
NS=`which niceshaper`
ECHO=`which echo`
if [ -z "$IP" ]; then
echo "Missing ip binary (iproute)"
exit 255
fi
if [ -z "$IPT" ]; then
echo "Missing iptables binary"
exit 255
fi
if [ -z "$NS" ]; then
echo "Missing niceshaper binary"
exit 255
fi
if [ -z "$ECHO" ]; then
echo "Missing echo binary"
exit 255
fi
$ECHO 1 > /proc/sys/net/ipv4/ip_forward
$ECHO 0 > /proc/sys/net/ipv4/conf/all/rp_filter
# === NiceShaper ===
$ECHO "Stopping NiceShaper"
$NS stop
# === Routing ===
$ECHO "Routing - Cleaning"
$IP route flush table 241 2>/dev/null
$IP route flush table 242 2>/dev/null
$IP rule del fwmark 0x1 table 241 2>/dev/null
$IP rule del fwmark 0x2 table 242 2>/dev/null
$ECHO "Routing - Table 241"
$IP route add ${wan1_net} dev ${wan1_iface} table 241 # Local route
$IP route add ${wan2_net} dev ${wan2_iface} table 241 # Local route
$IP route add ${lan_net} dev ${lan_iface} table 241 # Local route
$IP route add default via ${wan1_gw} table 241 # Default route through the uplink #1.
$ECHO "Routing - Table 242"
$IP route add ${wan1_net} dev ${wan1_iface} table 242 # Local route
$IP route add ${wan2_net} dev ${wan2_iface} table 242 # Local route
$IP route add ${lan_net} dev ${lan_iface} table 242 # Local route
$IP route add default via ${wan2_gw} table 242 # Default route through the uplink #2
$ECHO "Routing - Rules"
$IP rule add fwmark 0x1 table 241
$IP rule add fwmark 0x2 table 242
# === Packets marking ===
$ECHO "Creating iptables filters - packets marking"
$IPT -t mangle -F PREROUTING 2>/dev/null
$IPT -t mangle -F routemark 2>/dev/null
$IPT -t mangle -X routemark 2>/dev/null
$IPT -t mangle -N routemark
$IPT -t mangle -A routemark -i ${wan1_iface} -j MARK --set-mark 0x1
$IPT -t mangle -A routemark -i ${wan2_iface} -j MARK --set-mark 0x2
$IPT -t mangle -A routemark -i ${lan_iface} -p tcp -m multiport --dports ${isp2_ports_tcp} -j MARK --set-mark 0x2
$IPT -t mangle -A routemark -i ${lan_iface} -m mark ! --mark 0x2 -j MARK --set-mark 0x1
$IPT -t mangle -A routemark -j CONNMARK --save-mark
$IPT -t mangle -A PREROUTING -m state --state ESTABLISHED,RELATED -j CONNMARK --restore-mark
$IPT -t mangle -A PREROUTING -m state --state NEW -j routemark
# === NAT ===
$ECHO "Creating iptables filters - NAT"
$IPT -t nat -F POSTROUTING
$IPT -t nat -A POSTROUTING -o ${wan1_iface} -s ${lan_net} -j SNAT --to ${wan1_ip}
$IPT -t nat -A POSTROUTING -o ${wan2_iface} -s ${lan_net} -j SNAT --to ${wan2_ip}
# === NiceShaper ===
$ECHO "Starting NiceShaper"
$NS start
Last two classes are responsible for upload. Filters classify packets based on source address and outgoing interface. This interface changes depending on routing.
To summarize how to distinguish by which uplink the packets are routed. In the case of download, we use packet mark value, as outgoing interface is always the same (it's the LAN interface). In the case of upload, it's proper and comfortable to use outgoing interface. In this case, we don't need to explicitly indicate interface as it is the class interface.
Now, you should proceed to duplicate this set of classes for each host in network.
To simplify and compact the classes file, it's useful to use macro. The proposed one here is foreach-pair macro, which generates a copy of this set of classes for each defined "name - last IP octed" pair.