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.


How to disable auto suspend when I close laptop lid?

Edit /etc/systemd/logind.conf and make sure you have,


which will make it ignore the lid being closed. (You may need to also undo the other changes you’ve made).

Full details over at the archlinux Wiki.

The man page for logind.conf also has the relevant information,

   HandlePowerKey=, HandleSuspendKey=, HandleHibernateKey=,
       Controls whether logind shall handle the system power and sleep
       keys and the lid switch to trigger actions such as system power-off
       or suspend. Can be one of ignore, poweroff, reboot, halt, kexec,
       suspend, hibernate, hybrid-sleep and lock. If ignore logind will
       never handle these keys. If lock all running sessions will be
       screen locked. Otherwise the specified action will be taken in the
       respective event. Only input devices with the power-switch udev tag
       will be watched for key/lid switch events.  HandlePowerKey=
       defaults to poweroff.  HandleSuspendKey= and HandleLidSwitch=
       default to suspend.  HandleHibernateKey= defaults to hibernate.


x86 pslldq to Loongson psllq

x86 pslldq 指令逻辑左移字节为单位的数据,而转换成龙芯的MMI只能使用 dsll 和 dsrl 指令模拟实现,需要特别注意的是 dsll 和 dsrl 指令移动的数据是以位为单位的。

/* SSE: pslldq (bytes) */
#define _mm_psllq(_D, _d, _s, _s64, _tf)                    \
        "subu %["#_tf"], %["#_s64"], %["#_s"] \n\t"         \
        "dsrl %["#_tf"], %["#_d"l], %["#_tf"] \n\t"         \
        "dsll %["#_D"h], %["#_d"h], %["#_s"] \n\t"          \
        "dsll %["#_D"l], %["#_d"l], %["#_s"] \n\t"          \
        "or %["#_D"h], %["#_D"h], %["#_tf"] \n\t"
pslldq $4, %xmm0 => mm_psllq(d, d, s32, s64, t)


看龙芯3A的 dmtc1 指令有多慢!

龙芯2F和3A处理器都实现了与 x86 MMX 基本兼容的 SIMD,即 MMI,该 ASE 是在浮点部件中的实现的,并且复用了 64-bit 的浮点寄存器(FPR)。在使用 MMI 时不可避免的会使用到通用寄存器向浮点器移动数据的情况,那么 dmtc1 的效率如何呢?

GPR 向 FPR 移动数据的指令共有3种:
mtc1 : 从 GPR 向 FPR 移动 32-bit 的数据,64-bit 平台上目标 FPR 的高 32-bit 清 0。
mthc1 : 从 GPR (低 32-bit)向 FPR 的高 32-bit 移动 32-bit 的数据,目标 FPR 的低 32-bit 数据保留。
dmtc1 : 从 GPR 向 FPR 移动 64-bit 数据。

从上面的说明可以看出, dmtc1 的功能是可以使用 mtc1 与 mthc1 模拟实现的,那么我们就设计个实验程序来验证一下这两条方式的时间开销分别如何吧。

for (i=0; i<100000000; i++) {
#if 0
    move $2, $3
    mtc1 $3, $f31
    dsra $3, 32
    mthc1 $3, $f31
    move $3, $2
    dmtc1 $3, $f31
    dmtc1 $3, $f31

在 MIPS64 系统上,每个循环中做8次GPR2FPR的数据移动,其 dmtc1 实现时间大概为 0m4.463s,而 mtc1 与 mthc1 组合实现为 0m3.857s,后者如不做寄存器的保存恢复,开销仅为 0m1.791s。


Redirect TCP transmissions over Socks5 proxy

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

下载、编译 HevSocks5TProxy

git clone git://
cd hev-lib
make static
cd ..
git clone git://
cd hev-socks5-tproxy

运行 HevSocks5TProxy

bin/hev-socks5-tproxy 10800 1080
# : 本地监听地址
# 10800 : 本地监听端口
# : Socks5 服务器地址
# 1080 : Socks5 服务器端口

用于本地主机,重定向所有的 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 10800

用于网关服务器,重定向所有的 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 10800

DNS 转发
对于 DNS 污染情况,参考 Forwarding DNS queries on TCP transport


Forwarding DNS queries on TCP transport

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

下载、编译 DNS Forwarder

git clone git://
cd hev-lib
make static
cd ..
git clone git://
cd hev-dns-forwarder

运行 DNS Forwarder

bin/hev-dns-forwarder 5300
# : 本地监听地址
# 5300 : 本地监听端口
# :  上游 DNS 服务器

用于本地主机,透明转发所有的本机 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 子系统中也有方法:

#include <linux/netfilter_ipv4.h>
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: 注意防火墻的配置。