Saturday, October 19, 2013

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:

  • wpa_supplicant
  • iw
  • ip
  • 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
    phy#0
    	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
    network={
    	ssid="gorilla"
    	#psk="testtest"
    	psk=4dfe1c985520d26a13e932bf0acb1d4580461dd854ed79ad1a88ec221a802061
    }
    

    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 192.168.1.113 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 192.168.1.113/24 brd 192.168.1.255 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
    192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.113 
    

    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 192.168.1.254 dev wlan0
    $ ip route show
    default via 192.168.1.254 dev wlan0 
    192.168.1.0/24 dev wlan0  proto kernel  scope link  src 192.168.1.113 
    
  8. ping external ip address to test connectivity
    $ ping 8.8.8.8
    PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
    64 bytes from 8.8.8.8: icmp_req=1 ttl=48 time=135 ms
    64 bytes from 8.8.8.8: icmp_req=2 ttl=48 time=135 ms
    64 bytes from 8.8.8.8: icmp_req=3 ttl=48 time=134 ms
    ^C
    --- 8.8.8.8 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.

Saturday, October 12, 2013

How to use the screen command to run a program unattended

screen is a powerful terminal session manager with many use cases. One such use case is to start a long-running Command Line Interface (CLI) program in a terminal session, detach the session while leaving the program running unattended, logout, and return to the same session later from another terminal.

Let's examine how you would use screen in a real-life situation.

Imagine the time is 15 minutes to the end of your work day. But before you can leave, you have to run a program that will run for an hour. You don't want to wait around until it finishes in order to check the output. What you want is to start the program, leave, and check the output when you get home.

Assuming you have access to the work machine from home, this is how you would do it using screen.

  1. Start a new screen session.

    From a shell, run this command:

    $ screen -S mondaySession
    

    Note that the existing screen is immediately reset to blank. You have a new terminal session.

    The -S parameter lets you specify a name for the session. This makes it easier for you to come back to it later.

  2. Start the hour-long program.
    $ ls -al *.sh
    -rwxr-xr-x 1 peter peter  399 Oct  6  2013 long.sh
    $ ./long.sh
    ...
    
  3. Detach the session.

    Detaching the session does not mean you are suspending its operation. In fact, the session, including the long program, is still running in the background. Detaching a session leaves the program running unattended while you travel home.

    To detach a session, send the appropriate command keyboard shortcut to screen. While a screen session is active, screen listens constantly for keyboard shortcuts. For this specific example, hit the key sequence Control-a d. This means press the Ctrl key and the 'a' key together and release, and then press the 'd' key.

    Note: All screen keyboard shortcuts begin with the Control-a key sequence.

    The terminal session is collapsed, and disappear from your sight for now. The prior session is brought back. You will see the session status as "detached":

    $ screen -S mondaySession
    [detached]
    $
    
  4. Logout

    At this point, you can even log out, and the session still persists.

  5. Resume the session.

    After you get home, login to the work machine, and run the following command.

    $ screen -r mondaySession
    

    The terminal session is brought back. Note that you have access to the session as if you have never left it before, including its history, and the output of the long program that you started earlier.

    $ ls -al *.sh
    -rwxr-xr-x 1 peter peter  399 Oct  6  2013 long.sh
    $ ./long.sh
    .............................
    Program ended successfully. 
    

Disclaimer:
No discussion nowadays about screen is complete without the following disclaimer. tmux is a newer command that does similar things as screen. You can achieve the same effect described in this blog post using tmux. For now, however, you are more likely to find screen installed on a Linux box than tmux. I still find it useful to know the screen command.

Tuesday, October 8, 2013

Allow root ssh login with public key authentication only

Often, ssh is configured to disallow root to login directly. To login, root first logins as a non-privileged user, and then do a sudo to become root.

There can be many reasons why you don't want root to login directly. You may be concerned about security. Brute force attacks by guessing the password are common. In addition to security, you may be concerned about traceability. If there are more than 1 administrator on a system, and they can all login as root, then it is impossible to trace who had done what (after all, it is the same root account).

As an alternative, we can configure sshd such that root can remote login directly, but only with public key authentication. From the security perspective, public key authentication offers much better protection than password. If being able to trace the user is not that important (say there is only 1 root user), then you may wish to consider such a configuration. Note: remote login by root using password authentication is still disallowed.

  1. As root, edit the sshd daemon configuration file (/etc/ssh/sshd_config).
  2. Modify the PermitRootLogin and the PubkeyAuthentication parameters to have the following values.
    PermitRootLogin without-password
    PubkeyAuthentication yes
    
  3. Restart the sshd daemon.
    $ service sshd restart