#!/bin/sh # COLUMS and ROWS should be set on the console, if not, use fallback if [ -z "$COLUMNS" ]; then if command -v tput; then COLUMNS=$(tput cols) else COLUMNS=80 fi fi h1() { STR="$*" if [ -n "$plain" ]; then echo "$STR" | tr '[:lower:]' '[:upper:]' echo "$STR" | sed 's/./=/g' else printf "\033[7m%-${COLUMNS}s\033[0m" "$STR" fi } h2() { STR="$*" if [ -n "$plain" ]; then echo "$STR" echo "$STR" | sed 's/./-/g' else printf "\033[1m%-${COLUMNS}s\033[0m" "$STR" fi } ul() { if [ -n "$plain" ]; then echo "__${*}__" else printf "\033[54%s\033[0m" "$*" fi } em() { if [ -n "$plain" ]; then echo "**${*}**" else printf "\033[5m%s\033[0m" "$*" fi } overview() { cat < more [file] > e.g., 'cat very-long-file | less' most [file] > e.g., 'cat very-long-file | most' passwd Change user password pwgen Password generator reboot Restart the device reset Reset the shell prompt if it gets garbled $(h2 "Network Tools") ethtool [-h] Ethernet stats, and low-level MAC/PHY settings traceroute [-h] Trace the route ip packets follow going to a host tcpdump [-h] Display network packet headers in real-time arping [-h] Ping hosts by ARP requests/replies fping [-h] Send ICMP ECHO_REQUEST packets to multiple hosts ping [-h] Send ICMP ECHO_REQUEST packets to a network host lynx URL [-h] The text mode web browser netcalc [-h] Calculate IP network settings from a IP address netcat [-h] NetCat - TCP/IP swiss army knife (alias: nc) socat [-h] Multipurpose socket relay program ttyd [-h] Sharing a terminal over the web ifconfig [--help] See/Reconfigure available network interfaces route [--help] Edit the kernel's routing tables ifup | ifdown IFACE Bring up/down interfaces in /etc/network/interfaces ip [link|addr] Manage available network interfaces ip [rule|route] Manage routing tables bridge [link|vlan] Manage bridge ports and VLANs scp Securely copy a file to a remote host file system tftp Copy a file to/from a remote host ftpput Store a local file on a remote machine via FTP ftpget Retrieve a remote file via FTP wget Get a file using HTTP or FTP from a remote host $(h2 "Overview Commands") df -h List disk usage (in human readable format) free List memory usage ps List running processes show [arg] Show system status, see 'show help' for more info top Displays CPU usage and top list of running tasks $(h2 "Interesting Files") /etc/default/svc Command line args for service 'svc' (see above) /etc/rc.local Local setup, runs after all services have started /etc/network/ Directory of networking setup, see 'help net' $(h2 "Example Commands") cd /tmp; wget ftp://192.168.55.43/file && cat file cd /var/log; tftp -p -l messages 192.168.55.43 cat /proc/net/arp edit /etc/network/interfaces $(h2 "See Also") help edit Tutorial on VI and Mg editors help net Network set up introduction setup User friendly setup and diagnostic tool EOF } vi() { cat < Return to command mode with Esc EOF } emacs() { cat < means hold down the Control key while typing the character M- means hold down the Alt key while typing the character If you don't have a Meta/Alt key, you can use Esc instead. Press and release the Esc key and then type . This is equivalent to M-. $(h2 "Navigation") Though arrow keys, Home/End, and PgUp/PgDn usually work, using Mg over serial console can sometimes cause these keys to be mismapped by terminal program. C-f Move forward one character (can also use right arrow key) C-b Move backward one character (can also use left arrow key) C-p Move up one line (can also use up arrow key) C-n Move down one line (can also use down arrow key) M-f Move forward one word M-b Move backward one word C-a Move to beginning of line (can also use Home key) C-e Move to end of line (can also use End key) C-v Move forward one page (can also use PgDn/Page Down key) M-v Move backward one page (can also use PgUp/Page Up key) M-< Move to beginning of file M-> Move to end of file C-x g Move to line number $(h2 "Editing") All edit commands that kill (cut) text is placed in a kill ring (clipboard). Note: when marking text, there is no visual mark. C-_ Undo, also C-x u M-% Replace word/string in file, from cursor position M-q Reformat paragraph (set fill column with C-x f) C-s Search forward (type C-s again to find next) C-r Reversed search C-Space Set beginning of mark (beginning of selected text) C-x C-x Jump back and forth between mark and cursor position C-x h Mark whole buffer C-w Wipe (cut) region from mark to cursor position M-w Copy region from mark to cursor position C-y Yank (paste) text from kill ring C-k Kill (cut) to end of line M-Backspace Kill (delete) previous word M-d Kill (delete) next word C-d Delete character to the right C-o Open new line at cursor $(h2 "General Commands") C-g Abort current command C-l Recenter buffer on current line C-h b List all keybindings M-! Run shell command, output in new buffer C-z Suspend Mg, return to shell, use 'fg' to get back C-x C-f Open file C-x C-i Insert file at cursor position C-x C-s Save file C-x s Save file (interactive) C-x k Kill (close) file C-x C-b List open buffers (files) C-x b Switch to another buffer C-x C-c Exit $(h2 "Window Commands") C-x 0 Unsplit, keep other window C-x 1 Unsplit, keep this window C-x 2 Split window in two C-x o Go to other window C-x p Go to previous window C-x n Go to next window C-x ^ Enlarge this split EOF } editor() { case $1 in vi) vi ;; ed* | em* | mg) emacs ;; *) vi emacs cat <. This is the hostname and three last octets of the device's base MAC address. You can also use mDNS browsers or command line tools like mdns-scan $(h2 "VLAN Interfaces") A VLAN interface in Linux is an "upper" interface, e.g., 'eth0.1'. It is where you set an IP address and interact with th rest of the world. The base/raw/lower interface, here 'eth0', is the physical interface on which Ethernet packets ingress and egress with a VLAN tag. To create 'eth0.1': ip link add eth0.1 link eth0 vlan id 1 In Linux a VLAN interface is a "stackable" entity. Many VLAN interfaces can be built on top of each other. When injecting a packet on the top most interface, the kernel adds the corresponding VLAN "tag" when the packet goes down the order of stacked interfaces, and then finally hits the physical interface and proceeds to egress onto the media. ip link add eth0.1.2 link eth0.1 vlan id 2 Injecting a packet on 'eth0.1.2' creates a double-tagged VLAN frame when the packet egresses 'eth0'. The outermost tag has VID 1 and the inner VID is 2. VLAN interfaces can be used for many things, here we will focus on their use as upper interface on a bridge. $(h2 "Bridging Interfaces") A bridge is the correct name for a switch. In the context of this text, however, we will use the term to refer to the Linux bridge module in the kernel, which implements an advanced software switch. The Linux bridge supports "offloading" many switching functions to an underlying switching chipset, when available. This greatly simplifies managing that switch since the same tools one use to manage the bridge will, by extension, also be used to manage the switch. To create a bridge in Linux: ip link add br0 type bridge To add three ports (interfaces) to the bridge we use: ip link set eth0 master br0 ip link set eth1 master br0 ip link set eth2 master br0 Bring all ports and the bridge 'up' and you have a working switch! Any frame injected on eth0 (from the outside) can be switched to either of eth1, eth2, *or* br0. As soon as the bridge has learned where end devices are connected, none of the other ports will see the traffic -- like a regular switch. Note: these ports should not (cannot) have any IP address. Instead, any IP address is set on 'br0'. To disable IPv6 link-local address, set the /proc/sys/net/ipv6/conf/eth0/disable_ipv6 sysctl file to '1'. $(h2 "Bridging and VLANs") A VLAN-aware bridge works the same way, only with VLAN separation taken into account. All communication, as well as MAC address learning, is limited to ports in the same VLAN. The syntax is slightly different and requires a few more steps: ip link add br0 type bridge vlan_filtering 1 ip link set eth0 master br0 ip link set eth1 master br0 ip link set eth2 master br0 ip link set eth3 master br0 To assign ports to different VLANs, and make sure they are regular "access" ports (untagged). We assign eth0 and eth1 to VLAN 1 and the others to VLAN 2: bridge vlan add vid 1 dev eth0 pvid untagged bridge vlan add vid 1 dev eth1 pvid untagged bridge vlan add vid 2 dev eth2 pvid untagged bridge vlan add vid 2 dev eth3 pvid untagged Here's the twist, to be able to reach the bridge (switch) itself from each VLAN, we need to ensure the bridge itself is a tagged member of each VLAN: bridge vlan add vid 1 dev br0 self bridge vlan add vid 2 dev br0 self This way we can add VLAN interfaces on top of br0, which we in turn can set a static or dynamic IP address on: ip link add vlan1 link br0 type vlan id 1 ip link add vlan2 link br0 type vlan id 2 The resulting stack of interfaces look like this: : vlan1 : vlan2 Layer-3 :: IP Networking \\ : / _________________________ .-------------. | br0 | Layer-2 :: Switching '-------------' _________________________ / | : | \\ eth0 eth1 : eth2 eth3 Layer-1 :: Link layer : $(h2 "Persistent Configuration") A simple end device can get by with the following in /etc/network/interfaces: auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp This brings up both the loopback (required for UNIX networking to function), and the (presumed only) Ethernet interface. The loopback gets its standard address, 127.0.0.1, and eth0 will request its IP address using DHCP. To set up the bridge example (above), is actually quite a lot easier than using the command line ip and bridge tools. Create the file 'bridge': edit /etc/network/interfaces.d/bridge Paste in the following content: iface e0 bridge-access 1 iface e1 bridge-access 1 iface e2 bridge-access 2 iface e3 bridge-access 2 auto br0 iface br0 bridge-ports e0 e1 e2 e3 bridge-vlan-aware yes bridge-stp on bridge-vids 1 2 auto vlan1 iface vlan1 inet dhcp vlan-id 1 vlan-raw-device br0 auto vlan2 iface vlan2 inet static vlan-id 2 vlan-raw-device br0 address 192.168.2.1/24 Notice how 'vlan1' only has a DHCP and 'vlan2' uses a static address. It is possible to combine the two if needed. Use 'inet dhcp' and add an 'address' statement to the iface stanza. $(h2 "Port Classification") The bundled 'show' script is a very handy tool. It use several tricks to make information about the system more accessible. On switching capable hardware products, switch ports are identified early at system bootstrap and placed in the 'port' group. See 'ip link' output: ... 4: e0: master br0 state UP $(em "group port") link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff ... When running in Qemu or other hardware it may be useful to manually classify certain interfaces as ports. This can be achieved in many ways, here we show two. First /etc/mactab, which is read at boot to rename interfaces according their matching MAC address, one interface per line: e0 52:54:00:12:34:56 e1 52:54:00:12:34:57 e2 52:54:00:12:34:58 e3 52:54:00:12:34:59 Another way is to add something like this to /etc/rc.local: for port in eth0 eth1 eth3 eth4; do ip link set \$port group port done $(h2 "Interesting Files") - /etc/dhcpcd.conf General DHCP and ZeroConf (LL) settings - /etc/network/interfaces The original, useful for small setups - /etc/network/interfaces.d/* Snippets, useful for non-trivial setups - /etc/mactab Rename interfaces: 'NAME16CHARS WHITESPACE MAC' - /etc/sysctl.conf Interface and TCP/IP settings, e.g., routing - /etc/sysctl.d/* Snippets, useful for per-subsystem settings $(h1 "Summary") All persistent networking is set up in /etc/network/interfaces using the program ifupdown-ng. The tools to reconfigure networking at runtime are: ifup [-a] [IFACES] ifdown [-a] [IFACES] When changing the configuration at runtime you usually have to bring the affected interfaces down (ifdown e0 e1 e2 e3), if they were set up with /etc/network/interfaces before. Then do the change, and bring it all up again. Both tools understand dependencies between interfaces, so when a 'ifup -a' command is received it brings up all interfaces: adding links to br0 before adding VLANs, the vlan1 and vlan2 interfaces on top so it of it all. Then finally it can start the DHCP client on vlan1 and set the static IP address on vlan2. $(em ">>> Be careful with these tools when logged in remotely! <<<") EOF } topic() { topic=$1 [ -n "$1" ] && shift case $topic in ed*) # shellcheck disable=SC2068 editor $* ;; net*) networking ;; *) overview ;; esac } if [ "$1" = "-p" ]; then shift pager="cat" plain="yes" else if command -v most; then pager=most elif command -v less; then pager="less -R" elif command -v more; then pager="more" else pager="cat" fi fi if [ -t 1 ] ; then fn=$(mktemp /tmp/system-help.XXXXXX) # shellcheck disable=SC2086,SC2068 topic $@ >"$fn" $pager "$fn" rm "$fn" else topic "$*" fi