Linux simple source policy routing

Dual network connections


Routing policy
* Transmit via eth0 when source address is
* Transmit via eth1 when source address is


# eth0
ifconfig eth0 up
ip rule add from table 251
ip route add default via dev eth0 src table 251

# eth1
ifconfig eth1 up
ip rule add from table 252
ip route add default via dev eth1 src table 252


Configuring Bonding Manually via Sysfs

Configuring Bonding Manually via Sysfs

	Starting with version 3.0.0, Channel Bonding may be configured
via the sysfs interface.  This interface allows dynamic configuration
of all bonds in the system without unloading the module.  It also
allows for adding and removing bonds at runtime.  Ifenslave is no
longer required, though it is still supported.

	Use of the sysfs interface allows you to use multiple bonds
with different configurations without having to reload the module.
It also allows you to use multiple, differently configured bonds when
bonding is compiled into the kernel.

	You must have the sysfs filesystem mounted to configure
bonding this way.  The examples in this document assume that you
are using the standard mount point for sysfs, e.g. /sys.  If your
sysfs filesystem is mounted elsewhere, you will need to adjust the
example paths accordingly.

Creating and Destroying Bonds
To add a new bond foo:
# echo +foo > /sys/class/net/bonding_masters

To remove an existing bond bar:
# echo -bar > /sys/class/net/bonding_masters

To show all existing bonds:
# cat /sys/class/net/bonding_masters

NOTE: due to 4K size limitation of sysfs files, this list may be
truncated if you have more than a few hundred bonds.  This is unlikely
to occur under normal operating conditions.

Adding and Removing Slaves
	Interfaces may be enslaved to a bond using the file
/sys/class/net//bonding/slaves.  The semantics for this file
are the same as for the bonding_masters file.

To enslave interface eth0 to bond bond0:
# ifconfig bond0 up
# echo +eth0 > /sys/class/net/bond0/bonding/slaves

To free slave eth0 from bond bond0:
# echo -eth0 > /sys/class/net/bond0/bonding/slaves

	When an interface is enslaved to a bond, symlinks between the
two are created in the sysfs filesystem.  In this case, you would get
/sys/class/net/bond0/slave_eth0 pointing to /sys/class/net/eth0, and
/sys/class/net/eth0/master pointing to /sys/class/net/bond0.

	This means that you can tell quickly whether or not an
interface is enslaved by looking for the master symlink.  Thus:
# echo -eth0 > /sys/class/net/eth0/master/bonding/slaves
will free eth0 from whatever bond it is enslaved to, regardless of
the name of the bond interface.

Changing a Bond's Configuration
	Each bond may be configured individually by manipulating the
files located in /sys/class/net//bonding

	The names of these files correspond directly with the command-
line parameters described elsewhere in this file, and, with the
exception of arp_ip_target, they accept the same values.  To see the
current setting, simply cat the appropriate file.

	A few examples will be given here; for specific usage
guidelines for each parameter, see the appropriate section in this

To configure bond0 for balance-alb mode:
# ifconfig bond0 down
# echo 6 > /sys/class/net/bond0/bonding/mode
 - or -
# echo balance-alb > /sys/class/net/bond0/bonding/mode
	NOTE: The bond interface must be down before the mode can be

To enable MII monitoring on bond0 with a 1 second interval:
# echo 1000 > /sys/class/net/bond0/bonding/miimon
	NOTE: If ARP monitoring is enabled, it will disabled when MII
monitoring is enabled, and vice-versa.

To add ARP targets:
# echo + > /sys/class/net/bond0/bonding/arp_ip_target
# echo + > /sys/class/net/bond0/bonding/arp_ip_target
	NOTE:  up to 16 target addresses may be specified.

To remove an ARP target:
# echo - > /sys/class/net/bond0/bonding/arp_ip_target

To configure the interval between learning packet transmits:
# echo 12 > /sys/class/net/bond0/bonding/lp_interval
	NOTE: the lp_inteval is the number of seconds between instances where
the bonding driver sends learning packets to each slaves peer switch.  The
default interval is 1 second.

Example Configuration
	We begin with the same example that is shown in section 3.3,
executed with sysfs, and without using ifenslave.

	To make a simple bond of two e100 devices (presumed to be eth0
and eth1), and have it persist across reboots, edit the appropriate
file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the

modprobe bonding
modprobe e100
echo balance-alb > /sys/class/net/bond0/bonding/mode
ifconfig bond0 netmask up
echo 100 > /sys/class/net/bond0/bonding/miimon
echo +eth0 > /sys/class/net/bond0/bonding/slaves
echo +eth1 > /sys/class/net/bond0/bonding/slaves

	To add a second bond, with two e1000 interfaces in
active-backup mode, using ARP monitoring, add the following lines to
your init script:

modprobe e1000
echo +bond1 > /sys/class/net/bonding_masters
echo active-backup > /sys/class/net/bond1/bonding/mode
ifconfig bond1 netmask up
echo + /sys/class/net/bond1/bonding/arp_ip_target
echo 2000 > /sys/class/net/bond1/bonding/arp_interval
echo +eth2 > /sys/class/net/bond1/bonding/slaves
echo +eth3 > /sys/class/net/bond1/bonding/slaves

See also:

Windows 7 有线局域网组播接收丢包调试

一有线局域网实时流媒体组播传输应用从 Windows 10 迁移至 Windows 7 平台后,迁移后传输质量下降明显。

对比实验发现在同一发送端的同一组播窗口中,运行在 Windows 7 系统上的接收端效果明显劣于 Windows 10 接收端。

分析接收端的收到的数据包发现,Windows 7 平台的接收端存在明显的丢包现象。于是排查了这两个方面:
1. Win7 网卡驱动较 Win10 较旧。
2. Socket 默认接收缓冲区是否太小。

针对第1点,在将 Win7 网卡驱动升级至最新后无明显改善。:(
针对第2点,显式设置了接收缓冲区为 1MB 后,接收质量得到明显改善。:)


How to connect to a WPA/WPA2 WiFi network using Linux command line

This is a step-to-step guide for connecting to a WPA/WPA2 WiFi network via the Linux command line interface. The tools are:
1. wpa_supplicant
2. iw
3. ip
4. ping

iw is the basic tool for WiFi network-related tasks, such as finding the WiFi device name, and scanning access points. wpa_supplicant is the wireless tool for connecting to a WPA/WPA2 network. ip is used for enabling/disabling devices, and finding out general network interface information.

The steps for connecting to a WPA/WPA2 network are:

1. Find out the wireless device name.

    $ /sbin/iw dev
    	Interface wlan0
    		ifindex 3
    		type managed

The above output showed that the system has 1 physical WiFi card, designated as phy#0. The device name is wlan0. The type specifies the operation mode of the wireless device. managed means the device is a WiFi station or client that connects to an access point.

2. Check that the wireless device is up.

    $ ip link show wlan0
    3: wlan0: (BROADCAST,MULTICAST) mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
        link/ether 74:e5:43:a1:ce:65 brd ff:ff:ff:ff:ff:ff

Look for the word “UP” inside the brackets in the first line of the output.

In the above example, wlan0 is not UP. Execute the following command to bring it up:

    $ sudo ip link set wlan0 up  
    [sudo] password for peter: 

Note: you need root privilege for the above operation.

If you run the show link command again, you can tell that wlan0 is now UP.

    $ ip link show wlan0
    3: wlan0: (NO-CARRIER,BROADCAST,MULTICAST,UP) mtu 1500 qdisc mq state DOWN mode DEFAULT qlen 1000
        link/ether 74:e5:43:a1:ce:65 brd ff:ff:ff:ff:ff:ff

3. Check the connection status.

    $ /sbin/iw wlan0 link
    Not connected.

The above output shows that you are not connected to any network.

4. Scan to find out what WiFi network(s) are detected

    $ sudo /sbin/iw wlan0 scan
    BSS 00:14:d1:9c:1f:c8 (on wlan0)
            ... sniped ...
    	freq: 2412
    	SSID: gorilla
    	RSN:	 * Version: 1
    		 * Group cipher: CCMP
    		 * Pairwise ciphers: CCMP
    		 * Authentication suites: PSK
    		 * Capabilities: (0x0000)
            ... sniped ...

The 2 important pieces of information from the above are the SSID and the security protocol (WPA/WPA2 vs WEP). The SSID from the above example is gorilla. The security protocol is RSN, also commonly referred to as WPA2. The security protocol is important because it determines what tool you use to connect to the network.

5. Connect to WPA/WPA2 WiFi network.
This is a 2 step process. First, you generate a configuration file for wpa_supplicant that contains the pre-shared key (“passphrase”) for the WiFi network.

    $ sudo -s
    [sudo] password for peter: 
    $ wpa_passphrase gorilla >> /etc/wpa_supplicant.conf 
    ...type in the passphrase and hit enter...

wpa_passphrase takes the SSID as the single argument. You must type in the passphrase for the WiFi network gorilla after you run the command. Using that information, wpa_passphrase will output the necessary configuration statements to the standard output. Those statements are appended to the wpa_supplicant configuration file located at /etc/wpa_supplicant.conf.

Note: you need root privilege to write to /etc/wpa_supplicant.conf.

    $ cat /etc/wpa_supplicant.conf 
    # reading passphrase from stdin

The second step is to run wpa_supplicant with the new configuration file.

    $ sudo wpa_supplicant -B -D wext -i wlan0 -c /etc/wpa_supplicant.conf
    -B means run wpa_supplicant in the background.
    -D specifies the wireless driver. wext is the generic driver.
    -c specifies the path for the configuration file.

Use the iw command to verify that you are indeed connected to the SSID.

    $ /sbin/iw wlan0 link
    Connected to 00:14:d1:9c:1f:c8 (on wlan0)
    	SSID: gorilla
    	freq: 2412
    	RX: 63825 bytes (471 packets)
    	TX: 1344 bytes (12 packets)
    	signal: -27 dBm
    	tx bitrate: 6.5 MBit/s MCS 0

    	bss flags:	short-slot-time
    	dtim period:	0
    	beacon int:	100

6. Obtain IP address by DHCP

    $ sudo dhclient wlan0

Use the ip command to verify the IP address assigned by DHCP. The IP address is from below.

    $ ip addr show wlan0
    3: wlan0:  mtu 1500 qdisc mq state UP qlen 1000
        link/ether 74:e5:43:a1:ce:65 brd ff:ff:ff:ff:ff:ff
        inet brd scope global wlan0
        inet6 fe80::76e5:43ff:fea1:ce65/64 scope link 
           valid_lft forever preferred_lft forever

7. Add default routing rule.
The last configuration step is to make sure that you have the proper routing rules.

    $ ip route show dev wlan0  proto kernel  scope link  src 

The above routing table contains only 1 rule which redirects all traffic destined for the local subnet (192.168.1.x) to the wlan0 interface. You may want to add a default routing rule to pass all other traffic through wlan0 as well.

    $ sudo ip route add default via dev wlan0
    $ ip route show
    default via dev wlan0 dev wlan0  proto kernel  scope link  src 

8. ping external ip address to test connectivity

    $ ping
    PING ( 56(84) bytes of data.
    64 bytes from icmp_req=1 ttl=48 time=135 ms
    64 bytes from icmp_req=2 ttl=48 time=135 ms
    64 bytes from icmp_req=3 ttl=48 time=134 ms
    --- ping statistics ---
    3 packets transmitted, 3 received, 0% packet loss, time 2000ms
    rtt min/avg/max/mdev = 134.575/134.972/135.241/0.414 ms

The above series of steps is a very verbose explanation of how to connect a WPA/WPA2 WiFi network. Some steps can be skipped as you connect to the same access point for a second time. For instance, you already know the WiFi device name, and the configuration file is already set up for the network. The process needs to be tailored according to your situation.


Redirect TCP transmissions over Socks5 proxy

重定向 TCP 传输通过 Socks5 代理,此方案用于 Linux 平台。

下载、编译 HevSocks5TProxy

git clone git://
cd hev-socks5-tproxy
git submodule init
git submodule update

运行 HevSocks5TProxy

bin/hev-socks5-tproxy conf/main.ini
; main.ini





用于本地主机,重定向所有的 TCP 传输经过 Socks5 代理

sudo iptables -t nat -A OUTPUT -d -j RETURN # Bypass,远程 Socks5 服务器地址不通过代理
sudo iptables -t nat -A OUTPUT -m tcp -p tcp -j REDIRECT --to-port 1088

用于网关服务器,重定向所有的 TCP 传输经过 Socks5 代理

sudo iptables -t nat -A OUTPUT -d -j RETURN # Bypass,远程 Socks5 服务器地址不通过代理
sudo iptables -t nat -A PREROUTING -m tcp -p tcp -j REDIRECT --to-port 1088

DNS 转发
转发 UDP 协议的 DNS 查询至 TCP 协议传输,目前可以有效的抵御某些组织的 DNS 污染,此方案用于 Linux 平台。

用于本地主机,透明转发所有的本机 DNS 查询

sudo iptables -t nat -A OUTPUT -m udp -p udp --dport 53 -j REDIRECT --to-port 5300

或直接设置本地的 DNS 服务器为,并将 Forwarder 的本地监听端口修改为 53。

用于网关服务器,透明转发所有网关服务的主机的 DNS 查询

sudo iptables -t nat -A PREROUTING -m udp -p udp --dport 53 -j REDIRECT --to-port 5300


Linux netfilter REDIRECT target 构建透明代理原理

构建透明代理至于需要满足两个条件:1. 能够劫持应用程序产生的需代理的网络数据包。2. 能够获得这些数据包的原目的地址。

Linux netfilter 有一个 REDIRECT target,可用于 nat 表的 PREROUTING 和 OUTPUT 链上,其工作流程是将上述的两个链上命中的数据包的目的地址修改成(即重定向)该包进入网卡的主 IP 地址,如果是本地回环网络产生的包即重定向到。目标端口从参数指定,协议支持 tcp, udp, dccp or sctp。

从上面的情况看,Linux netfilter 的 REDIRECT target 可以实现透明代理的第一个条件,而第二个条件在强大的 Linux netfilter 子系统中也有方法:


struct sockaddr_in orig_addr;
socklen_t orig_addr_len = sizeof (orig_addr);
if (0 == getsockopt(client_fd, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr*) &orig_addr, &orig_addr_len)) {
        printf ("This is original destination address => %s:%u\n", inet_ntoa (orig_addr.sin_addr), ntohs (orig_addr.sin_port));


Firefox for Android 代理设置

目前发现 Android 平台的浏览器原生支持代理配置的仅 Firefox for Android(官方下载),不仅支持 HTTP、HTTPS 和 Socks4、5,还支持 PAC 脚本。

在 Firefox 中访问 about:config,使用 proxy 过滤器并的找到 network.proxy.socks, network.proxy.socks_port, network.proxy.socks_remote_dns, network.proxy.type 并更改成图中配置。


将 PAC 脚本放至于 /sdcard/proxy.pac,在 Firefox 中访问 about:config,使用 proxy 过滤器并的找到 network.proxy.autoconfig_url, network.proxy.type 并更改成图中配置。



QEMU 高性能网络配置

QEMU 的网络配置最简单的是 -net user 模式,从 Guest OS 角度看 Host OS 为其提供了 NAT 和 DHCP 服务。此模式也有两点明显的不足之处:
1. 网络传输性能较差。
2. Host OS 访问 Guest OS 网络服务、Guest OS 互相访问对话网络服务都不方便。

这里推荐使用 -net tap 模式,大概的工作原理是 QEMU 进程会使用 Linux tun 子系统创建一个虚拟的 tap 类型的网络接口,这个虚拟的链路的一端在 Host OS 角度即是一个 Ethernet 类型的网络接口,另一端被 QEMU 连接到其在 Guest OS 中虚拟化的 Ethernet 网络接口上。Tap 类型的接口工作在链路层,链路上承载的协议与常规的 Ethernet 相比无多余的限制。这种情况看上去就像是 Host 与 Guest 都有一个网络接口直连着。

Host OS 还可以创建一个 Bridge,然后将 QEMU 创建的 tap 类型的网口都加入到同一个 Bridge 上面,这样就相当于将多个 Guest 及 Host 的一个网口都连接到同一个交换机上。当然创建多个 Bridge 进行分组管理也可以。

Host OS

sudo brctl addbr br0
sudo brctl stp br0 off
sudo ifconfig br0 up
qemu-system-x86_64 --enable-kvm -net nic,model=virtio -net tap,helper=/usr/lib/qemu/qemu-bridge-helper ...

Guest OS

sudo ifconfig eth0 up
sudo route add default gw

Guest OS 中如需连接外部网络,有两种方式:
1. NAT 模式,Host OS 视 Guest OS 所处的 Bridge 是一个内网,由 Host OS 提供 NAT 服务,配置与常规的 Linux NAT 配置一样。
2. Bridge 模式,只需将 Host OS 上连接外网的网口也增加到 Guest OS 所属的 Bridge 中。

Windows virtio 驱动
Guest 中如果安装 Windows 操作系统,需要安装 virtio (net) 驱动,详见:

Tips: 注意防火墻的配置。


一种 HTTP 会话劫持的防御方法

HTTP 会话劫持也是 TCP 会话劫持,它是利用了 TCP Seqnum 的可预见性来伪造有效的响应包,并抢先响应客户端同时使得客户端主动丢弃原服务器的响应包。在这个层面想区分哪一个响应包是伪造的是有困难的,但结合实际情况考虑问题也还有一些思路。

1. 劫持程序不是什么都劫持了,只有符合条件被命中的 HTTP 请求才会劫持的,那也就是说劫持程序需要一个完整或至少包含它需要的信息的请求才可以劫持,我想 Host, QueryString, Referer 这些应该少不了。
2. 劫持程序不希望维护 TCP 上下文进行流重组。因为维护起来成本比较高。
3. 基于上一点来说,劫持程序也就不希望一个 HTTP 请求被拆分在两个或多个包中传输。

从实际检测来看,大多数的 HTTP 请求还是包含在一个独立的 TCP 包中传输的,只有很少的情况被拆分了。我想你一定想到了什么了,对!我们就假设当前在用的劫持程序都没有维护 TCP 传输上下文进行流重组,那么人为对前向链路上的流进行强制拆分,就应该能够逃过被劫持。

实现的方式应该会有很多,我在应用层代理层面实现了一个简单的原型,方式是将前向链路的 Buffer size 强制在了 16 字节。代码托管在 Github =>

从抓包来看,HTTP 请求在传输时被拆分了:

packet 0:[syn]
packet 1: GET / HTTP/1.1\r\n
packet 2: Host: xxxx
packet 3: ...