Table of parts: https://docs.google.com/document/d/1IIOkivkS0lV9QIL16b_OjT480BxZHQfKswvvS-CVZlw/view

"In the web of Linux" - Linux and networking. Part 4.

Reminiscence: IP network stack:

Address

Socket

Linux command to view address

Physical layer

Port number

-

-

MAC layer

MAC address

packet socket

ip link, ifconfig

Network layer

IP address

raw socket

ip addr, ifconfig

Transport layer

IP:port

usual socket

netstat --inet -na

Sockets

Server TCP socket workflow:

int socket(int domain, int type, int protocol);

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

int listen(int sockfd, int backlog);

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Client TCP socket workflow:

int socket(int domain, int type, int protocol);

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

ssize_t send(int sockfd, const void *buf, size_t len, int flags);

ssize_t recv(int sockfd, void *buf, size_t len, int flags);

Socket address

Generally represents IP:port

        struct sockaddr

        struct sockaddr_in

        struct sockaddr_in6

        struct sockaddr_un

        struct sockaddr_storage

Getting socket address

Example using strace and netcat

$ strace -e trace=network,readv nc -lp 5555

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 4

setsockopt(4, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0

bind(4, {sa_family=AF_INET, sin_port=htons(5555),

sin_addr=inet_addr("0.0.0.0")}, 16) = 0

listen(4, 128) = 0

accept(4, {sa_family=AF_INET, sin_port=htons(44458),

sin_addr=inet_addr("127.0.0.1")}, [128->16]) = 5

readv(5, [{iov_base="1234\n", iov_len=8192}], 1) = 5

1234 

$ strace -e trace=network,writev,fcntl nc 127.0.0.1 5555

socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3

setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0

fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0

connect(3, {sa_family=AF_INET, sin_port=htons(5555),

sin_addr=inet_addr("127.0.0.1")}, 16)

= -1 EINPROGRESS (Operation now in progress)

getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0

1234

writev(3, [{iov_base="1234\n", iov_len=5}], 1) = 5

Main exercise

Develop a connection forwarder. The program should listen a TCP port and propagate each connection to other TCP port. Data should be exchanged in both directions.

Написать программу, выполняющую проброс подключений TCP. Пользователь подключается в вашей программе, а та подключается куда-то ещё и обеспечивает двухсторонний обмен данными.

Necessary features:

(Bigger state-of-the-art project: socat)

Complications:

  1. UDP mode
  2. UNIX sockets
  1. User authentication
  2. SCM_RIGHTS
  1. IPv6 support
  2. Semi-closed sockets
  3. Multiple simultaneous clients (threaded)
  4. Multiple simultaneous clients (poll/select/epoll)
  1. EPOLLET
  1. raw or packet sockets
  2. stress testing tool
  3. Simple HTTP downloader
  4. Usage of getaddrinfo
  5. SCTP mode
  6. timeouts

RFCs

Documents that describe standards or something like that.

Excercise 2

Using poll/select/epoll, implement simple chat server with the following commands:

Describe your protocol in a RFC-like document.

Timeline:

  1. Publishing the first version of the document: Mar 13

If not: forced version to be implemented

  1. Assigning the client implementor: Mar 20

If not: poor assignment

  1. Comments: Mar 27

If not: no comments == no complaints about bad doc later

  1. Final version of the document: Apr 10

If not: free reign of client implementor and you need to adapt server later

  1. Server implementation:
  2. Client implementation:
  3. Testing: ...

If not: no credit

LANG=ru

Используя poll/select/epoll, реализуйте чат-сервер со следующими командами:

Вы должны описать ваш протокол в виде документа в стиле RFC.

Hints for the document:

For example, I have already got a letter with a text-based protocol using newlines as a separator between commands and space as a separator between command arguments. Second document about essentially the same protocol sans different command names and limitations  will need to be changed. Missing deadline => I give you a tricky, "innovative" document to implement a server for. If the document is incomplete and/or there are contradictions, implementor of the client may do that as one pleases, requiring you to amend both server and the document in accordance to the client.

Excercise 3

Get the document (but not a source code or a program) from other student and implement (using any technology) a client for it. Own and peer user names should be configurable from command line, received messages should be printed to stdout, read lines from stdin should be sent as the peer user.

LANG=ru

Получив документ (но не программу или исходный код) от другого студента, написать клиент для чат-сервера, используя любую технологию. Имя пользователя и пользователь для получения сообщений должны быть настраиваемыми (например, из командной строки). Полученные сообщения выводить в stdout, прочитанные из stdin строки посылать другому пользователю.

Ways to serve multiple clients simultaneously:

UDP. One socket can server multiple clients, no backpressure.

Nonblocking sockets + event loop. SOCK_NONBLOCK, fcntl O_NONBLOCK

Popular mode for many applications. Does not work for regular files in Linux.

Process (thread) per client + blocking sockets

Also popular mode, especially when accepting and serving a connection is done by different programs.

POSIX AIO: man 7 aio

Creates additional threads under the hood.

Not popular, slow.

---

Linux AIO: libaio, man 2 io_submit

Strictly no buffering (O_DIRECT), depends on filesystem, no sockets

May silently fall back to blocking behaviour.

What happens when one issues a http request?

curl http://example.com/

A. Resolve IP

Step 1: Get IP address of DNS server

/etc/resolv.conf

/etc/nsswitch.conf

Step 2: Determine if that IP is local or not?

$ ip route get to 192.168.99.1

192.168.99.1 dev wifi0 src 192.168.99.127

$ ip route get to 8.8.8.8

8.8.8.8 via 192.168.99.1 dev wifi0 src 192.168.99.127

Step 3: Get MAC address of that IP address

$ arp -n 192.168.99.1

Address      HWtype HWaddress         Flags Mask Iface

192.168.99.1 ether  00:23:cd:1d:71:ec C          wifi0

$ ip neigh get 192.168.99.1

Sorry, "neigh get" is not implemented :-(

$ ip neigh show to 192.168.99.1

192.168.99.1 dev wifi0 lladdr 00:23:cd:1d:71:ec DELAY

$ arping -i wifi0 192.168.99.1

$ arping -i wifi0 00:23:cd:1d:71:ec -T 192.168.99.1

Step 4: Send DNS request and wait for reply

$ dig +short example.com @192.168.99.1

93.184.216.34

B. Connect to the resolved IP

Previously steps 1-3 was for the IP of DNS server.

Now they are repeated, but for the IP of example.com.

$ ip route get 93.184.216.34

93.184.216.34 via 192.168.99.1 dev wifi0 src 192.168.99.127 cache

$ ip neigh show to 192.168.99.1

192.168.99.1 dev wifi0 lladdr 00:23:cd:1d:71:ec REACHABLE

C. Data exchange

Exercise 1

Issue commands to view IP and MAC address of your DNS server

Issue commands to view IP and MAC address of bsu.by

Exercise 2:

Use tcpdump/wireshark to observe steps above

Exercise 3:

Use strace to observe what data is being sent and received.

Network configuration and debugging

Working with network interfaces

# ethtool wifi0

Settings for wifi0:

         Link detected: yes

ip link

ip addr

ip route

/proc/sys/net/ipv4/

/proc/sys/net/ipv4/conf/

/proc/sys/net/ipv4/conf/wifi0/

iptables -t nat -A POSTROUTING ! -d 127.0.0.0/8 ! -o lo -j MASQUERADE

Exercise 1:

Set up additional IP address on local network using "ip addr" command. Check connectivity.

ip addr add 192.168.50.1/24 dev eth0

Exercise 2:

Try set up two networks + routing, maybe + NAT.

Check (with tcpdump/Wireshark) that it really routes.

On host:

ip addr add 192.168.51.2/24 dev eth0

ip route add 192.168.50.0/24 dev eth0 via 192.168.51.1

On router:

echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding

Git

https://docs.google.com/document/d/169eb2IAu4pc7g61YyeNgG66C5f8IV0T0nNUhV7vyo6M/edit?usp=sharing

Wireless networking

Main wireless AP properties:

Simple commands to connect to passwordless wlan

iwlist wlan0 scan

Ifconfig wlan0 up

iwconfig wlan0 essid "My AP name"

Using wpa_supplicant manually

  1. Start wpa_supplicant

wpa_supplicant -i wlan0 -c myconfigfile.conf

Initial config:

ctrl_interface=/var/run/wpa_supplicant

update_config=1

  1. Start wpa_cli

wpa_cli -p /var/run

  1. Issue scan command:

> scan

OK

<3>CTRL-EVENT-SCAN-STARTED

<3>CTRL-EVENT-SCAN-RESULTS

  1. Inspect the results

> scan_results

bssid / frequency / signal level / flags / ssid

f4:9f:f3:a4:65:97    2437    -29    [WPA2-PSK-CCMP][ESS]    HAP

  1. Add and conflgure the network

> add_network

0

> set_network 0 ssid "HAP"

OK

> set_network 0 key_mgmt WPA-PSK

OK

> set_network 0 psk "qwer1234"

OK

  1. Enable the network

> enable_network 0

OK

<3>CTRL-EVENT-SCAN-STARTED

<3>CTRL-EVENT-SCAN-RESULTS

<3>SME: Trying to authenticate with f4:9f:f3:a4:65:97 (SSID='HAP' freq=2437 MHz)

<3>Trying to associate with f4:9f:f3:a4:65:97 (SSID='HAP' freq=2437 MHz)

<3>Associated with f4:9f:f3:a4:65:97

<3>CTRL-EVENT-REGDOM-CHANGE init=COUNTRY_IE type=COUNTRY alpha2=CN

<3>WPA: Key negotiation completed with f4:9f:f3:a4:65:97 [PTK=CCMP GTK=CCMP]

<3>CTRL-EVENT-CONNECTED - Connection to f4:9f:f3:a4:65:97 completed [id=0 id_str=]

  1. Save config

> save_config

OK

New config file:

ctrl_interface=/tmp/wpast

update_config=1

network={

    ssid="HAP"

    psk="qwer1234"

    key_mgmt=WPA-PSK

}

  1. Configure IP address

# dhclient -d wlan0

...

DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 6

DHCPREQUEST on wlan0 to 255.255.255.255 port 67

DHCPOFFER from 192.168.43.1

DHCPACK from 192.168.43.1

...

bound to 192.168.43.10 -- renewal in 1532 seconds.

  1. Configure name server (if not configured)
  2. Connected

Creating your own network with hostapd

  1. Install hostapd
  2. Create hostapd configuration file (by copying a sample one)
  1. start hostapd

Using interface wlan0 with hwaddr 48:5d:60:a3:9f:eb and ssid 'qweeeq'

  1. Configure IP address

ip addr add 192.168.151.1/24 dev wlan0

  1. Try connecting, supplying manual IP address, check that ping works
  2. Configure and start DHCP and or DNS server

dnsmasq -d -i wlan0 -F 192.168.151.100,192.168.151.200,/24,5m

  1. Try to connect with automatic IP assignment
  2. Enable forwarding and NAT (see "Network configuration and debugging" part of this document).
  3. Check that your internet-enabled AP works
  4. Try Wireshark/tcpdump to see traffic

SOHO network administration

DHCP server

DNS server

Linux and router

IPtables, nftables

OpenVPN

quality of service

Particular network services

nginx

sshd