6.1. Определение существующих установок TCP/IP

[+]6.1.1. ifconfig(8) — настройки сетевых интерфейсов
[+]6.1.2. netstat(1)
[+]6.1.2.1. Таблица маршрутизации
[+]6.1.2.2. Статистика
[+]6.1.2.3. Работающие интернет сервисы и открытые сокеты
[+]6.1.2.3.1. Открытие TCP соединения (тройное рукопожатие)
[+]6.1.2.3.2. Закрытие TCP соединения
[+]6.1.3. route(8)
[+]6.1.4. /etc/resolv.conf(5)
[+]6.1.5. hostname(1)

Описание.  Кандидат BSDA должен уметь определить IP адреса системы, маску подсети, шлюз, первичный и вторичный сервер DNS и имя хоста.

Практика. ifconfig(8), netstat(1), resolv.conf(5), route(8), hostname(1)

Комментарий

Итак, в этом разделе речь идёт не о настройке сети, а лишь об определении текущих настроек. Разберёмся в возможностях упомянутых здесь утилит.

Во имя целостности повествования мы выйдем за рамки задач поставленных в экзаменационном билете. Надеюсь читатель не останется внакладе.

6.1.1. ifconfig(8) — настройки сетевых интерфейсов

Утилита ifconfig(8) предназначена для настройки сетевых интерфейсов и диагностики текущих настроек. Как мы и договаривались, в данном разделе мы изучаем только возможности по диагностике, а настройкой займёмся в другом разделе (См. Раздел 6.2.2, «ifconfig(8) — настройки сетевых интерфейсов»).

1-й уровень OSI[1] (физический):

  • наличие несущей в проводе подведённом к интерфейсу;
  • характеристики Ethernet;

2-й уровень OSI (канальный):

  • MAC-адрес (он же hardware address);
  • флаги интерфейса (см расшифровку флагов сетевых интерфейсов ниже);

3-й уровень OSI (сетевой):

  • MTU — Maximum Transfer Unit — максимальный размер пакета, который можно передать/принять через данный интерфейс. Пакет имеется ввиду на сетевом уровне модели OSI, порция информации на канальном уровне называется «кадр»;
  • IP-адрес;
  • IPv6-адрес;
  • маска подсети;
  • широковещательный адрес;

Вот пример того, как может выглядеть вывод команды ifconfig(8):

$ifconfig -a 1
rl0: 2 flags=8802<BROADCAST,SIMPLEX,MULTICAST> mtu 1500 3
        options=8<VLAN_MTU> 4
        inet xxx.yyy.zzz.180 netmask 0xffffff80 broadcast xxx.yyy.zzz.255 5
        ether 00:80:48:2d:f7:15 6
        media: Ethernet autoselect (100baseTX <full-duplex>) 7
        status: active 8
rl1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        options=8<VLAN_MTU>
        inet 172.16.0.1 netmask 0xfffffffc broadcast 172.16.0.3
        inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255 9
        ether 4c:00:10:13:15:1d
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active
pflog0: flags=141<UP,RUNNING,PROMISC> mtu 33208 10
pfsync0: flags=0<> mtu 2020
lp0: flags=8851<UP,POINTOPOINT,RUNNING,SIMPLEX,MULTICAST> mtu 1500 11
        inet 10.0.0.1 --> 10.0.0.2 netmask 0xff000000
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 12
        inet 127.0.0.1 netmask 0xff000000
        
1 Команде ifconfig(8) необходимо указать по каким интерфейсам она должна вывести сведения. Если вместо этого указать аргумент -a будут выведены сведения обо всех интерфейсах, с опцией -u только об интерфейсах активных в данный момент, точнее об интерфейсах с установленным флагом UP (в данном случае rl1, pflog0 и lo0). В NetBSD и OpenBSD флаг -u отстутствует. В FreeBSD интерфейс указывать необязательно: если вы вызываете ifconfig(8) без аргументов, по умолчанию подразумевается ключ -a. В NetBSD и OpenBSD обязательно надо указать или интерфейс или ключ -a.
2 Указание на то, что следующий абзац относится к интерфейсу rl0. Специально для поклонников Linux отметим: в BSD принято называть интерфейсы по именам отвечающих за них драйверов. За сетевые карты на чипсете RealTek отвечает драйвер rl(4). Узнать о специфических настройках для устройств на остове этого чипсета можно из справочной страницы man 4 rl.
3

Флаги в угловых скобках подробно описаны ниже. В них собрана информация о возможностях интерфейса и текущем режиме его работы.

mtu — maximum transfer unit в байтах.

4
5 Характеристики интерфейса на сетевом уровне: IP-адрес, маска подсети и широковещательный адрес. Характреристики в адресном пространстве IPv6 сообщаются отдельной строкой и здесь непоказаны.
6 Аппаратный адрес (он же MAC-адрес) устройства. (Канальный уровень.)
7 media — характеристики передающей среды (физический уровень). Ethernet autoselect — скорость обмена данными автоматически определяется при взаимодействии с устройством на противоположном конце провода, выбирается наивысшая скорость из поддерживаемых обоими устройствами, если среда не поддерживает сигнал на этой скорости (например сопротивление в проводе слишком большое) а оба устройства договорились о передаче на большой скорости, необходимо хотя бы одно из них вручную перевести на более низкую скорость передачи данных; 100baseTX: 100 — выбрана скорость передачи данных 100 Мб/сек, base — для передачи используется вся частотная полоса (у ADSL-модема это не так: он может одновременно на одной частоте передавать обычный телефонный сигнал, а на другой интернет-трафик), TX — для передачи используется витая пара (twisted pair); full-duplex — возможна одновременная передача данных в обе стороны, если это не так, будет написано half-duplex.
8 Физическая характеристика — наличие несущей в проводе. Возможные значения active или no carrier. В последнем случае, это значит, что провод вышел из гнезда, или его разорвал экскаватор, или прибор с той стророны выключен.
9 Здесь показан пример того, как выглядит конфигурация интерфейса, когда на нём поднято одновременно несколько IP-адресов (алиасов). В Linux в этом случае заводится новое устройство (например в дополнение к интерфейсу eth0 появляется eth0:0, eth0:1 и т.д.), что в ряде случаев бывает удобно. Так, если мы какому-нибудь сервису предписываем посылать пакеты через интерфейс rl1 неочевидно какой IP он будет использовать.
10 Это пример виртуального интерфейса. Данный интерфейс используется пакетным фильтром OpenBSD — pf(4). (В настоящий момент данный брандмауэр используется не только в OpenBSD, но так же и в FreeBSD начиная с версии 5.3 и в NetBSD.)
11 Это параллельный порт сконфигурированный для связи типа точка-точка.
12 И, наконец, кольцевой интерфейс.

Флаги сетевых интерфейсов (информацию о некоторых флагах можно получить из девятой страницы man(1), см. ifnet(9). Более полно флаги описаны в книге [McKusick-2004]):

UP
Интерфейс доступен для использования, т.е. сконфигурирован и готов передавать сообщения. Когда мы запускаем команду ifconfig(8) с опцией -u, мы выводим информацию именно об интерфейсах с этим флагом.
RUNNING
Интерфейсу (драйверу) выделены системные ресурсы. В принципе возможна ситуация, когда этот флаг не установлен, а флаг UP стоит. Разумеется, для функционирования устройства необходимы оба флага.
BROADCAST
С интерфейса можно передавать широковещательные пакеты.
MULTICAST
Поддерживаются широковещательные пакеты для группы адресов.
SIMPLEX
Интерфейс не ловит пакеты, которые он отправляет. В частности, при отправке широковещательного пакета, интерфейс сам не может его получить. Чтобы сеть при этом работала корректно, функция отправки широковещательного пакета в ядре делает вид, что она получила широковещательный пакет, когда она его отправляет.
PROMISC
Включён «неразборчивый» (promiscuous) режим. Интерфейс ловит все пакеты вне зависимости от того, кому они предназначены. Этим режимом могут пользоваться так называемые «снифферы» — программы для подслушивания сетевого трафика. В частности, программа tcpdump(1), предназначенная для диагностических целей.
ALLMULTI
Аналогично флагу PROMISC, но ловятся пакеты предназначенные группе адресов.
MONITOR
Режим контроля запрошенный пользователем: пакеты не передаются, а полученные пакеты уничтожаются после получения устройством bpf(4) (т.е. после попадания в tcpdump(1))
POINTTOPOINT
Интерфейс предназначен для соединения типа точка-точка.
LINK0, LINK1, LINK2
Флаги специфичны для канального уровня. Так, например для интерфейса SLIP, LINK0 означает, что разрешена сжатая передача (CSLIP), LINK1 — сжатая передача разрешена только при получении сжатого пакета с другого конца, LINK2 — все пакеты ICMP уничтожаются. (См. [Stevens-2003-ru])
LOOPBACK
Кольцевой интерфейс.
SMART
Интерфейс самостоятельно управляет своими маршрутами.
NOARP
Интерфейс не использует протокол ARP.
STATICARP
Интерфейс использует только статическую таблицу ARP
OACTIVE
Интерфейс занят выводом. Этот флаг устанавливается когда попытка ввода недопустима.
POLLING
Интерфейс в режиме опроса.
DEBUG
Включена отладка в драйвере интерфейса.

Здесь упомянуты не все возможные флаги, а лишь флаги упомянутые в [McKusick-2004]. В [Stevens-2003-ru] можно найти упоминание других флагов, например NOTRAILERS — управление концевой инкапсуляцией при формировании кадра из пакета. Полный обозор флагов не входит в наши цели.

Каждый флаг это некоторый бит в числе характеризующем состояние интерфейса. Это число приведено перед списком флагов в угловых скобках В ШЕСТНАДЦАТЕРИЧНОМ представлении. Так число 8843 переводится в двоичную систему как 1000100001000011 и означает набор флагов <UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST>. Здесь за флаг UP отвечает самый правый бит, BROADCAST — второй справа, RUNNING — 7-й справа. Переключая флаги нетрудно вычислить какой бит чему соответствует. Легко видеть, что для того, чтобы интерфейс работал, необходимо (но недостаточно), чтобы число было нечётным.

Некоторые флаги поддерживаются не во всех операционных системах, что связано, возможно (это мои домыслы), с разрядностью числа характеризующего состояние сетевого интерфейса в них. Так флаг STATICARP (20-й бит справа) есть только в FreeBSD и отсутствует в OpenBSD и NetBSD. То же относится к флагу MONITOR (19-й бит).

6.1.2. netstat(1)

Утилита netstat(1) предназначена для диагностики работы TCP/IP стека. Она выводит разнообразную информацию о работе сетевых интерфейсов на сетевом и транспортном уровнях:

  • Таблицу маршрутизации системы.
  • Статистику о трафике в целом, по протокольно, поинтерфейсно.
  • Список работающих в данный момент интернет сервисов и открытых сокетов.

6.1.2.1. Таблица маршрутизации

$ netstat -nr
Routing tables

Internet:
Destination        Gateway            Flags    Refs      Use  Netif Expire
default            xxx.yyy.zzz.254    UGS         0  1056785    rl0
127.0.0.1          127.0.0.1          UH          0    39839    lo0
172.16/30          link#2             UC          0        0    rl1
172.16.0.2         4c:00:10:54:dd:8e  UHLW        0    30428    rl1   1045
xxx.yyy.zzz.128/25 link#1             UC          0        0    rl0
xxx.yyy.zzz.254    00:50:8b:5c:98:4f  UHLW        1     1888    rl0   1189
          

Аргумент -r заставил команду netstat(1) напечатать таблицу маршрутизации, а -n заставил не заменять IP-адреса хостов на их имена.

Рассмотрение этой таблицы начнём с третьего столбца: флаги. Мы видим, что во всех строках стоит флаг U, это значит, что все марршруты в настоящий момент активны (Up). В строках посвящённых адресам 127.0.0.1, 172.16.0.2 и xxx.yyy.zzz.254 имеется флаг H, это значит, что данный адрес относится не к сети, а к хосту (Host). Такие маршруты имеют приоритет перед маршрутом к сети, таким образом, мы можем жёстко прописать маршрут к некоторой машине, даже если маршрут к сети в которой она находится — иной. Флаг G означает, что данная машина является шлюзом, поэтому при обращении к ней надо при инкапсулировании пакета в кадр заменить MAC-адрес машины которой предназначен пакет, на MAC-адрес шлюза (если MAC-адрес назначения почему-то известен). Дальнейшей маршрутизацией этого пакета будет заниматься шлюз. В данном разделе мы не обсуждаем вопрос откуда берутся маршруты.

Итак, пусть у нас есть три пакета, первый предназначен машине 172.16.0.2, второй xxx.yyy.zzz.200 и третий xxx.yyy.zzz.100.

Для первого пакета машина сразу находит запись с флагом H, понимает, что его надо отправить через интерфейс rl1, формирует Ethernet-кадр дописывая к IP пакету MAC-адрес машины 172.16.0.2 (4c:00:10:54:dd:8e) и интерфейса rl1 и отправляет пакет.

Для второго пакета запись в таблице маршрутизации с флагом H ненайдена, но найдена сеть xxx.yyy.zzz.128/25, которой принадлежит машина xxx.yyy.zzz.200. Флаг G отсутствует, поэтому формируется кадр с MAC адресом получающей стороны, и MAC-адресом интерфейса rl0. В таком виде кадр отсылается с интерфейса rl0.

Для третьего пакета, увы не найдено никаких маршрутов — хост xxx.yyy.zzz.100 машине неизвестен и ни одной сети он не принадлежит. Поэтому он направляется на маршрут по умолчанию — default xxx.yyy.zzz.254. Этот маршрут помечен флагом G, поэтому даже если мы знаем MAC-адрес получателя, что маловероятно, но вполне реально, мы заменяем его на MAC-адрес шлюза xxx.yyy.zzz.254 (00:50:8b:5c:98:4f), дописываем MAC-адрес интерфейса rl0 и отсылаем, в надежде на то, что шлюз знает что делать с этим пакетом.

В колонке «Use»сказано сколько пакетов прошло по тому или иному маршруту.

Маршрут действует в течение некоторого периода времени, после которого он должен быть или выброшен из таблицы маршрутизации или продлён. Оставшееся время жизни маршрута указывается в колонке «Expire» в секундах.

6.1.2.2. Статистика

$netstat -ni
Name    Mtu Network       Address              Ipkts Ierrs    Opkts Oerrs  Coll
rl0    1500 <Link#1>      00:80:48:2d:f7:15 51129385     0  1081628     0     0
rl0    1500 xxx.yyy.zzz.1 xxx.yyy.zzz.180     459392     -   421556     -     -
rl1    1500 <Link#2>      4c:00:10:13:15:1d  4116747     0  7617322     1     0
rl1    1500 172.16/30     172.16.0.1         1604297     -  6705688     -     -
pflog 33208 <Link#3>                               0     0        0     0     0
pfsyn  2020 <Link#4>                               0     0        0     0     0
lo0   16384 <Link#5>                           39988     0    39988     0     0
lo0   16384 your-net      127.0.0.1            39863     -    39863     -     -
          

Как и раньше, аргумент -n подавляет раскрытие адресов в имена. Из этой таблицы мы можем определить сколько пакетов было передано через тот или иной сетевой интерфейс в ту или иную стророну. Чтобы измерить трафик в байтах можно добавить ещё два аргумента: -b чтобы выводить информацию в байтах и -d чтобы сообщать об отброшенных (droped) пакетах:

$ netstat -nibd
Name    Mtu Network       Address              Ipkts Ierrs     Ibytes    Opkts Oerrs     Obytes  Coll Drop
rl0    1500 <Link#1>      00:80:48:2d:f7:15 51141983     0 1282650574  1082806     0  221186433     0   0
rl0    1500 xxx.yyy.zzz.1 xxx.yyy.zzz.180     459467     -  295420865   421634     -  136159516     -   -
rl1    1500 <Link#2>      4c:00:10:13:15:1d  4117877     0 3436868162  7618633     1 1263505336     0   0
rl1    1500 172.16/30     172.16.0.1         1604327     - 3270648640  6705718     -  168875424     -   -
pflog 33208 <Link#3>                               0     0          0        0     0          0     0   0
pfsyn  2020 <Link#4>                               0     0          0        0     0          0     0   0
lo0   16384 <Link#5>                           39992     0    4836343    39992     0    4836343     0   0
lo0   16384 127           127.0.0.1            39867     -    4803206    39867     -    4803206     -   -
          

Итак, через интерфейс rl0 на машину с MAC-адресом 00:80:48:2d:f7:15 (как мы видели раньше, это шлюз) прошло наружу 1082806 пакетов, или 221186433 байт. В обратном направлении пришло 51141983 пакета или 1282650574 байт.

Обратите так же внимание на столбец «Coll» — это счётчик коллизий. В сетях Ethernet 10BaseTX, 100BaseTX и 1000BaseTX, построенных на коммутаторах, а не повторителях (на свитчах, а не на хабах), в принципе не может быть никаких коллизий, так как домен коллизий сводится всего к двум машинам благодаря коммутации на канальном уровне, а две машины не могут совершить коллизию, так как они соединены многожильным кабелем и TX/RX сигналы разнесены по разным парам проводов.

Мы можем смотреть как меняется статистика во времени. Если мы укажем команде netstat(1) в аргументе -w период обновления в секундах.

$ netstat -w2
            input        (Total)           output
   packets  errs      bytes    packets  errs      bytes colls
        51     0       4077          1     0        178     0
        46     0       3676          1     0        178     0
        49     0       3794          1     0        178     0
        51     0       3779          1     0        178     0
^C
          

Здесь программа netstat(1) каждые две секунды отчитывается о том, сколько пакетов и байт входит в машину через все интерфесы вместе.

Запустив в фоновом режиме утилиту ping(8), посылающую ICMP-пакеты через интерфейс rl1, мы можем видеть эти пакеты командой netstat(1)

$ ping 172.16.0.2 > /dev/null &
$ netstat -w2 -I rl1
            input          (rl1)           output
   packets  errs      bytes    packets  errs      bytes colls
         2     0        196          2     0        196     0
         2     0        196          2     0        196     0
         2     0        196          2     0        196     0
         2     0        196          2     0        196     0
^C
$ fg
ping 172.16.0.2 > /dev/null
^C
          

Утилита ping(8) посылает пакеты раз в секунду, поэтому netstat(1) с опцией -w2, добавляя по строке раз в две секунды, каждый раз видит по 2 пакета.

6.1.2.3. Работающие интернет сервисы и открытые сокеты

[Замечание]Замечание
Аналогичную информацию можно получить так же при помощи программы sockstat(1). См Раздел 6.3.2, «sockstat(1)»

При запуске утилиты netstat(1) без каких либо аргументов, можно получить информацию об открытых сокетах. Мы запустим утилиту как всегда с опцией -n с тем, чтобы адреса не преобразовывались в имена, и номера сервисов тоже были бы представлены числами:

$ netstat -n
Active Internet connections
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
tcp4       0     52  194.87.141.180.22      62.117.108.7.1833   ESTABLISHED 1
tcp4       0      0  194.87.141.180.22      62.117.108.7.64544  ESTABLISHED
tcp4       0      0  172.16.0.1.53882       172.16.0.2.22       ESTABLISHED
tcp4       0      0  194.87.141.180.22      62.117.108.7.64344  ESTABLISHED
tcp4       0      0  194.87.141.180.22      62.117.108.7.64286  ESTABLISHED
tcp4       0      0  194.87.141.180.22      62.117.108.7.64242  ESTABLISHED
udp4       0      0  127.0.0.1.123          *.* 2
udp4       0      0  172.16.0.1.123         *.*
udp4       0      0  194.87.141.180.123     *.*
udp4       0      0  127.0.0.1.53           *.*
udp4       0      0  172.16.0.1.53          *.*
udp4       0      0  194.87.141.180.53      *.*
udp4       0      0  172.16.0.1.706         172.16.0.2.2049 3
udp4       0      0  172.16.0.1.743         172.16.0.2.2049
udp4       0      0  172.16.0.1.690         172.16.0.2.2049
udp4       0      0  172.16.0.1.633         172.16.0.2.2049
udp4       0      0  172.16.0.1.701         172.16.0.2.2049
udp4       0      0  172.16.0.1.887         172.16.0.2.2049
udp4       0      0  172.16.0.1.991         172.16.0.2.2049
udp4       0      0  172.16.0.1.852         172.16.0.2.2049
Active UNIX domain sockets
Address  Type   Recv-Q Send-Q    Inode     Conn     Refs  Nextref Addr
c10897a8 stream      0      0        0 c1089af0        0        0
c1089af0 stream      0      0        0 c10897a8        0        0
c10892bc stream      0      0        0 c10899d8        0        0
c10899d8 stream      0      0        0 c10892bc        0        0
c10888c0 stream      0      0        0 c1089ec4        0        0
c1089ec4 stream      0      0        0 c10888c0        0        0
c108971c stream      0      0        0 c1088af0        0        0
c1088af0 stream      0      0        0 c108971c        0        0
c1089834 stream      0      0        0 c10894ec        0        0
c10894ec stream      0      0        0 c1089834        0        0
c1088834 stream      0      0        0 c1089a64        0        0 /var/run/dovecot/login/default 4
c1089a64 stream      0      0        0 c1088834        0        0
c1089c94 stream      0      0        0 c1089604        0        0
c1089604 stream      0      0        0 c1089c94        0        0
c1089e38 stream      0      0        0 c10887a8        0        0 /var/run/dovecot/login/default
c10887a8 stream      0      0        0 c1089e38        0        0
c1089460 stream      0      0        0 c10891a4        0        0
c10891a4 stream      0      0        0 c1089460        0        0
c1209000 stream      0      0        0 c108894c        0        0 /var/run/dovecot/login/default
c108894c stream      0      0        0 c1209000        0        0
c108994c stream      0      0        0 c108871c        0        0
c108871c stream      0      0        0 c108994c        0        0
c10893d4 stream      0      0 c1867738        0        0        0 /var/run/dovecot/auth-worker.53422
c1088a64 stream      0      0        0 c1089118        0        0
c1089118 stream      0      0        0 c1088a64        0        0
c1209118 stream      0      0 c1ac0c60        0        0        0 /var/run/dovecot/login/default
c1089b7c stream      0      0 c138f738        0        0        0 /tmp/mysql.sock
c1089d20 stream      0      0 c11fed68        0        0        0 /var/run/cgisock.536
c10882bc stream      0      0        0 c1088230        0        0
c1088230 stream      0      0        0 c10882bc        0        0
c108808c stream      0      0        0 c1088000        0        0
c1088000 stream      0      0        0 c108808c        0        0
c1088c08 stream      0      0 c10b4a50        0        0        0 /var/run/rpcbind.sock
c1089000 stream      0      0 c1078d68        0        0        0 /var/run/devd.pipe
c10883d4 dgram       0      0        0 c1088e38        0 c1089348
c1089348 dgram       0      0        0 c1088e38        0 c1088460
c10884ec dgram       0      0        0 c1088dac        0        0
c1088460 dgram       0      0        0 c1088e38        0 c1088348
c1088348 dgram       0      0        0 c1088e38        0 c10881a4
c10881a4 dgram       0      0        0 c1088e38        0 c1088118
c1088118 dgram       0      0        0 c1088e38        0 c1088604
c1088604 dgram       0      0        0 c1088e38        0 c1088b7c
c1088b7c dgram       0      0        0 c1088e38        0 c1088c94
c1088c94 dgram       0      0        0 c1088e38        0        0
c1088d20 dgram       0      0 c108a108        0        0        0 /var/named/var/run/log
c1088dac dgram       0      0 c108a210        0 c10884ec        0 /var/run/log
c1088e38 dgram       0      0 c108a318        0 c10883d4        0 /var/run/logpriv
c1088ec4 dgram       0      0 c1078210        0        0        0 /var/run/log
          

Отчёт команды netstat(1) состоит из двух частей: в первой перечислены открытые в настоящий момент соединения интернет, а во второй перечислены используемые системой сокеты.

1 Как видно, в настоящий момент, наша машина xxx.yyy.zzz.180 имеет шесть соединений по протоколу ssh (порт 22). Из них пять открыто из Интернет на нашу машину (с хоста xyz.yzx.zxy.yxz) и одно открыто с нашей машины, с адреса 172.16.0.1 на машину 172.16.0.2. Все шесть соединений открыты и потому пребывают в состоянии ESTABLISHED.
2 На портах 123 (NTP, служба времени) и 53 (DNS) висят какие-то службы и ждут входящего соединения (поскольку никаких флагов тут не обозначено)
3 С хоста 172.16.0.2 импортировано несколько каталогов по NFS.
4 В этой части таблицы перечислены активные в настоящий момент сокеты. Некоторые из них имеют интерфейс файлов.

Программа netstat(1) выводит сведения о состоянии TCP (см. флаг ESTABLISHED выше), согласно [RFC-793]. Что такое «состояние TCP» и какие они бывают, мы описываем в Раздел B.1.4.3.4, «Состояние соединения TCP». Подробное обсуждение этой темы можно найти в [Stevens-2003-ru].

При помощи флага -a можно получить информацию обо всех сокетах, в том числе пребывающих в состоянии LISTEN.

# netstat -na | grep LISTEN
tcp4       0      0  *.587                  *.*                    LISTEN
tcp4       0      0  *.25                   *.*                    LISTEN
tcp4       0      0  *.22                   *.*                    LISTEN
tcp4       0      0  *.80                   *.*                    LISTEN
tcp4       0      0  *.143                  *.*                    LISTEN
tcp4       0      0  *.965                  *.*                    LISTEN
tcp4       0      0  *.2049                 *.*                    LISTEN
tcp4       0      0  *.701                  *.*                    LISTEN
tcp4       0      0  *.730                  *.*                    LISTEN
tcp4       0      0  *.111                  *.*                    LISTEN
tcp4       0      0  127.0.0.1.953          *.*                    LISTEN
tcp4       0      0  127.0.0.1.53           *.*                    LISTEN
tcp4       0      0  172.19.0.2.53          *.*                    LISTEN
          

Таким образом, можно узнать какие порты прослушиваются нашей машиной.

Видимо необходимо некоторое пояснение к термину «состояние сокета». Рассмотрим как осуществляется открытие и закрытие соединения TCP:

6.1.2.3.1. Открытие TCP соединения (тройное рукопожатие)

Пусть клиент открывает соединение с сервером. Тогда говорят, что клиент осуществляет активное открытие соединения, а сервер пассивное открытие соединения. Изначально сервер находится в состоянии LISTEN.

  1. Клиент посылает запрос на открытие соединения и переходит в состояние SYN-SENT.
  2. Сервер получает этот запрос и отправляет в одном пакете два сообщения: 1) подтверждение получения запроса на открытие соединения, 2) свой собственный запрос на открытие соединения. При этом сервер переходит из состояния LISTEN в состояние SYN-RECEIVED.
  3. Клиент получает подтверждение на запрос об открытии соединения и запрос на открытие соединения, посланные в одном пакете. В ответ он посылает подтверждение серверу. После этого клиент уже может посылать данные. Он может начать посылать данные сразу, в одном пакете со своим подтверждением. Таким образом он переходит из состояния SYN-SENT в состояние ESTABLISHED. Сервер получив от него подтверждение начинает принимать данные и тоже переходит в состояние ESTABLISHED (из состояния SYN-RECEIVED).

Теперь стороны могут обмениваться данными в обе стороны, в состоянии ESTABLISHED, обе стороны высылают друг другу пакеты с данными, время от времени присылая подтверждения о получении этих пакетов, причём в одном подтверждении может подтверждаться получение большого числа пакетов.

Процесс открытия соединения часто называется тройным рукопожатием, так как происходит обмен тремя пакетами в обеих направлениях. (См. так же Раздел B.1.4.3.2, «Открытие соединения TCP, тройное рукопожатие».)

6.1.2.3.2. Закрытие TCP соединения

Пусть клиент закрывает соединение с сервером. Тогда говорят, что клиент выполняет активное закрытие, а сервер пассивное закрытие. Изначально оба хоста пребывают в состоянии ESTABLISHED.

  1. Клиент посылает запрос на закрытие соединения и переходит в состояние FIN-WAIT-1
  2. Сервер получил этот запрос и выслал подтверждение о его получении. Теперь он перешёл в состояние CLOSE-WAIT
  3. Клиент получил подтверждение и перешёл из FIN-WAIT-1 в FIN-WAIT-2. Говорят, что это соединение «полузакрыто»: клиент не может посылать данные серверу, но сервер может посылать данные клиенту, ведь он ещё не закрыл соединение. Клиент сказал, что разговор окончен, а сервер ответил, что он услышал, но сервер ещё не сказал, что разговор окончен, он может продолжать посылать данные.
  4. Сервер дозрел и тоже стал закрывать соединение. Он посылает клиенту запрос на закрытие соединения и переходит из CLOSE-WAIT в LAST-ACK
  5. Клиент получил этот пакет и послал подтверждение. При этом он перешел в состояние TIME-WAIT. Если подтверждение посланное клиентом недошло до сервера, сервер вновь пошлёт запрос на закрытие соединения и клиент снова на него отреагирует. А если со стороны сервера ничего не пришло, значит он получил подтверждение. Время для TIME-WAIT выбирается такое, в течение которого пакеты заведомо успевают пройти в обе стороны. Когда сервер получает подтверждение на свой запрос, он переходит из состояния LAST-ACK в CLOSED (или снова LISTEN). Клиент, переходит из TIME-WAIT в CLOSED если в течение указанного периода времени он не получил никаких ответов.

6.1.3. route(8)

Утилита route(8) больше предназначена для управления таблицей маршрутизации, однако с её помощью тоже можно получить некоторую диагностическую информацию. Допустим нам надо узнать маршрут к машине с адресом 192.168.3.4

$ route get 192.168.3.4
   route to: 192.168.3.4
destination: default
       mask: default
    gateway: xxx.yyy.zzz.254
  interface: rl0
      flags: <UP,GATEWAY,DONE,STATIC>
 recvpipe  sendpipe  ssthresh  rtt,msec    rttvar  hopcount      mtu     expire
       0         0         0         0         0         0      1500         0
        

В NetBSD и OpenBSD есть так же команда show, которая заставляет route(8) распечатать таблицу маршрутизации целиком, подобно netstat -r:

$ route -n show
Routing tables

Internet:
Destination      Gateway            Flags
default          **************     UG
127.0.0.0        localhost          UG
**************   localhost          UGH
192.168.26.0     link#1             U
**************   0:10:e0:0:e9:cd    UH
192.168.26.2     0:10:e0:0:7c:46    UH
192.168.26.7     0:e:a6:66:2d:c5    UH
BASE-ADDRESS.MCA localhost          U

Internet6:
Destination      Gateway            Flags
default          ****************** UG
default          ****************** UG
**************** ****************** UH
::127.0.0.0      ****************** UG
::224.0.0.0      ****************** UG
::255.0.0.0      ****************** UG
::ffff:0.0.0.0   ****************** UG
2002::           ****************** UG
2002:7f00::      ****************** UG
2002:e000::      ****************** UG
2002:ff00::      ****************** UG
fe80::           ****************** UG
fe80::%le0       link#1             U
fe80::%lo0       fe80::1%lo0        U
fec0::           ****************** UG
ff01::           ****************** U
ff02::%le0       link#1             U
ff02::%lo0       fe80::1%lo0        U
        

При помощи команды route monitor можно следить за изменениями маршрутной таблицы в реальном времени.

6.1.4. /etc/resolv.conf(5)

Когда машине надо обратиться к некоторому адресу в интернет, она должна преобразовать символьное имя машины (такое, как example.ru), в IP (или IPv6) адрес. Осуществляется это при помощи библиотечной функции gethostbyname(3). Типичное поведение этой функции выглядит так: 1) изучается файл /etc/hosts в котором перечислено какие имена соответствуют некоторым адресам; 2) затем, если поиск не дал результатов, при помощи resolver(3)'а осуществляются запросы к серверам DNS. На порядок этих действий можно влиять при помощи файла /etc/nsswitch.conf, это описано в Раздел 6.7, «Изменение порядка разрешения имён».

За работу resolver'а отвечает настроечный файл /etc/resolv.conf. Вот его мы и рассмотрим в данном разделе.

Файл /etc/resolv.conf является настроечным файлом для клиентской части системы DNS — resolver'а. Синтаксис файла предельно прост: в нём перечисляются DNS сервера в порядке убывания приоритета. Перед IP адресом сервера DNS указывается ключевое слово nameserver.

nameserver 127.0.0.1
nameserver 192.168.0.1
search somewhere.ru ru ua org
        

Здесь сказано, что для разрешения имён в IP-адреса, нужно сперва обратиться к локальной машине (предполагается, что на ней запущен свой собственный named(8)), а если обратиться к нему неудастся (если он не запущен), обратиться к DNS на машине 192.168.0.1. Здесь сервер DNS на машине 127.0.0.1 называется первичным DNS-сервером (primary), а 192.168.0.1 — вторичным (secondary). Обратите внимание: если первичный сервер DNS не сможет разрешить имя, он вернёт отрицательный ответ и запрос к вторичному серверу выполнен не будет (ведь ответ пришёл, просто он отрицательный).

resolver использует для работы первые три сервера DNS.

Допустим, мы хотим разрешить имя host, а в нашем файле /etc/resolv.conf имеются только записи типа nameserver. В этом случае resolver попытается найти машину host., такой машины конечно же нет, следующее действие resolver'а будет таким: он возьмёт имя домена в котором находится наша машина и допишет этот домен. Если наша машина имеет имя client.somewhere.ru, то resolver попытается разрешить имя host.somewhere.ru.

На это поведение можно влиять двумя способами: 1) с помощью директивы domain указать какой-нибудь другой домен и тогда поиск будет осуществляться в нём.

2) при помощи директивы search явно перечислить через пробел домены в которых следует производить поиск, как это показано в листинге выше. В нашем примере если resolver не сможет разрешить имя host, то он допишет к нему домен «somewhere.ru» и попробует разрешить имя host.somewhere.ru, затем будет осуществлена попытка разрешить имя host.ru, host.ua и host.org:

$ host -v host
Trying domain "somewhere.ru" 1
rcode = 3 (Non-existent domain), ancount=0
Trying domain "ru" 2
rcode = 0 (Success), ancount=1
The following answer is not authoritative:
The following answer is not verified as authentic by the server:
host.ru 1800 IN A       195.2.70.38
For authoritative answers, see:
host.ru 1800 IN NS      dns1.zenon.net
host.ru 1800 IN NS      dns2.zenon.net
Additional information:
dns1.zenon.net  1412 IN A       195.2.64.38
dns2.zenon.net  1412 IN A       195.2.83.38
        
1 Здесь осуществлена попытка разрешить имя host.somewhere.ru. Эта попытка завершилась неудачей — такого хоста нет.
2 Теперь система пытается разрешить имя host.ru. Такое имя существует, машина с этим именем имеет IP 195.2.70.38, за неё отвечает два сервера DNS: dns1.zenon.net и dns2.zenon.net с IP адресами 195.2.64.38 и 195.2.83.38. (Про команду host(1) мы будем говорить в Раздел 6.5, «Запрос к серверу DNS».)

Попробуем обнаружить машину соответствующую озеру Леприндо, расположенному в Читинской области на БАМе у подножия горного массива Кодар:

$ host -v leprindo
Trying domain "somewhere.ru"
rcode = 3 (Non-existent domain), ancount=0
Trying domain "ru"
rcode = 3 (Non-existent domain), ancount=0
Trying domain "ua"
rcode = 3 (Non-existent domain), ancount=0
Trying domain "org"
rcode = 3 (Non-existent domain), ancount=0
Host not found.
        

Как видим, resolver выполнил 4 запроса к DNS, попытавшись обнаружить машины leprindo.somewhere.ru, leprindo.ru, leprindo.ua и leprindo.org, и потерпел неудачу.

Наконец, в этом файле можно задавать некоторые опции. Следующая строка во-первых, включает режим отладки, а во-вторых объявляет, что надо пытаться разрешить имя при помощи списка из директивы search, если в нём менее 2-х точек (а не одной, как по умолчанию). Т.е. по умолчанию, если в имени нет точек, то оно сперва ищется в списке доменов из директивы search, а со включённой ниже опцией это поведение распространяется на имена содержащие одну точку.

options debug ndots:2
        

После редактирования файла /etc/resolv.conf никаких специальных действий не требуется, изменения немедленно вступают в силу.

6.1.5. hostname(1)

Утилита hostname(1) служит для того, чтобы сообщить имя машины, на которой она запущена. Используется во множестве разнообразных скриптов. Имеет всего один необязательный аргумент служащий для удаления имени домена:

$ hostname
myhost.example.org
$ hostname -s
myhost
        


[1] О модели OSI можно прочитать в глоссарии OSI