четверг, 19 марта 2020 г.

Every decent algorithm book reflects the design philosophy of its author. For students seeking alternative presentations and viewpoints, we particularly recommend
the books of Corman, et. al [CLRS01], Kleinberg/Tardos [KT06], and Manber
[Man89].
Formal proofs of algorithm correctness are important, and deserve a fuller discussion than we are able to provide in this chapter. See Gries [Gri89] for a thorough
introduction to the techniques of program verification.
The movie scheduling problem represents a very special case of the generalindependent setproblem, which is discussed in Section 16.2 (page 528). The restriction
limits the allowable input instances to interval graphs, where the vertices of the
graphGcan be represented by intervals on the line and (i, j) is an edge ofGiff
the intervals overlap. Golumbic [Gol04] provides a full treatment of this interesting
and important class of graphs.
Jon Bentley’sProgramming Pearlscolumns are probably the best known collection of algorithmic “war stories.” Originally published in the Communications
of the ACM, they have been collected in two books [Ben90, Ben99]. Brooks’s The
Mythical Man Month[Bro95] is another wonderful collection of war stories, focused
more on software engineering than algorithm design, but they remain a source of
considerable wisdom. Every programmer should read all these books, for pleasure
as well as insight.

Steven S. Skiena
The Algorithm Design Manual


суббота, 21 декабря 2019 г.

Легковесный RDP-сервер на Debian 8 + XFCE (с русскоязычным интерфейсом)

1. Ставим Debian, выбираем русскую локаль
Если локаль по умолчанию английская, сменить её можно так:
https://wiki.debian.org/ChangeLanguage
# env | grep LANG
# export LANG=ru_RU.UTF-8
# dpkg-reconfigure locales


2. Настраиваем Iptables
Перед настройкой IPtables (запланировать перезагрузку через 10 минут)
shutdown -t 10 –r
shutdown –c


2.1. Создаем скрипт для iptables (не забываем chmod 0740)
nano /usr/local/firewall/firewall_static.sh

2.2. Правила
#!/bin/sh

PATH='/sbin'
ALLOW_SSH='10.10.10.0/24,192.168.1.1/32'
ALLOW_RDP='10.10.10.0/24,192.168.1.1/32'
WAN='eth0'

# Flush previous rules, delete chains and reset counters
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

# Default policies
iptables -P FORWARD DROP
iptables -P INPUT   DROP
iptables -P OUTPUT  DROP

# Disable source-routed packets
echo -n '0' > /proc/sys/net/ipv4/conf/all/accept_source_route
# Disable ICMP Redirect Acceptance
echo -n '0' > /proc/sys/net/ipv4/conf/all/accept_redirects
# Enable broadcast echo protection
echo -n '1' > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
# Enable bad error message protection
echo -n '1' > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

# Enable loopback traffic
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Enable statefull rules (after that, only need to allow NEW conections)
iptables -A INPUT   -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT


# Drop invalid state packets
iptables -A INPUT   -m conntrack --ctstate INVALID -j DROP
iptables -A OUTPUT  -m conntrack --ctstate INVALID -j DROP
iptables -A FORWARD -m conntrack --ctstate INVALID -j DROP

# Allow SSH management
iptables -A INPUT -i $WAN -s $ALLOW_SSH -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT

# Enable all outgoing traffic to internet
iptables -A OUTPUT -o $WAN -d 0.0.0.0/0 -j ACCEPT

# Allow RDP
iptables -A INPUT -i $WAN -s $ALLOW_RDP -p tcp --dport 3389 -m conntrack --ctstate NEW -j ACCEPT


## LOGGING to /var/log/messages
#iptables -A INPUT   -j LOG --log-level debug --log-prefix '[FW INPUT]:    '
#iptables -A OUTPUT  -j LOG --log-level debug --log-prefix '[FW OUTPUT]:   '
#iptables -A FORWARD -j LOG --log-level debug --log-prefix '[FW FORWARD ]: '


2.3 Создаем также правила для ipv6 в файле /usr/local/firewall/ipv6_firewall.sh
(не забываем chmod 0740)
#!/bin/sh
PATH='/sbin'

# Flush the tables to apply changes
ip6tables -F

#ACCEPT POLICY
ip6tables -P INPUT DROP #If it doesn't match a rule Drop it
ip6tables -P FORWARD DROP #NO ROUTING POLICY DROP
ip6tables -P OUTPUT ACCEPT #If it doesn't match a rule

########
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -m state --state ESTABLISHED,RELATED -A INPUT -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT


2.4. Добавляем . /usr/local/firewall/firewall_static.sh и . /usr/local/firewall/ipv6_firewall.sh
в /etc/rc.local перед exit0

2.5. Проверяем счетчики iptables
iptables -vL


3. Ставим XFCE
apt update
apt install mc
apt install xfce4 xfce4-goodies xorg dbus-x11 x11-xserver-utils


4. Собираем xrdp
https://github.com/neutrinolabs/xrdp/wiki/Building-on-Debian-8

apt-get install git autoconf libtool pkg-config gcc g++ make  libssl-dev libpam0g-dev libjpeg-dev libx11-dev libxfixes-dev libxrandr-dev  flex bison libxml2-dev intltool xsltproc xutils-dev python-libxml2 g++ xutils libfuse-dev libmp3lame-dev nasm libpixman-1-dev xserver-xorg-dev

mkdir Downloads
cd Downloads
git clone https://github.com/neutrinolabs/xrdp.git
git clone https://github.com/neutrinolabs/xorgxrdp.git


cd /home/user/Downloads/xrdp
./bootstrap
./configure --enable-fuse --enable-jpeg
make
make install


cd /home/user/Downloads/xorgxrdp
./bootstrap
./configure
make
make install


systemctl daemon-reload
systemctl enable xrdp.service
systemctl enable xrdp-sesman.service
systemctl start xrdp

systemctl status xrdp


5. Ставим браузер и офис с пакетом локализации
apt install iceweasel libreoffice xfonts-mathml libreoffice-l10n-ru myspell-ru hyphen-ru libreoffice-grammarcheck-ru libreoffice-help-ru mythes-ru

6. Создаём группу rdp-users и добавляем в неё пользователей
addgroup rdp-users
adduser <username> --ingroup rdp-users


7. Смотрим логи
tail -F /var/log/xrdp.log
tail -F /var/log/xrdp-sesman.log


8. Для того, чтобы добавить клавиатурный шорткат для смены раскладки в xfce сначала добавляем на панель индикатор раскладки, далее, щёлкнув по нему правой кнопкой переходим в настройку параметров и выбираем шорткат.





среда, 22 мая 2019 г.

Сервер strongswan ipsec + клиенты на Win10 и Ubuntu ч.4: настройка клиента на Ubuntu

1. apt install strongswan
2. В /etc/ipsec.secrets добавляем
<client_ID> <server_ID> : PSK <key>

!Ключ в такой записи добавляем без кавычек!

3. В /etc/ipsec.conf
conn VPN
        dpdaction=restart
        dpddelay=35s
        dpdtimeout=300s
        rekey=no
        left=%any
        leftid=<private_IP>
        right=<public_ip>
        rightsubnet = 0.0.0.0/0
        ike=aes256-sha2_256-modp1024!
        esp=aes256-sha2_256!
        authby=secret
        auto=add
        leftsourceip=%config

       
Комментарии:
- по умолчанию 'left' это локальная сторона. Только если IP адрес или разрешенный FQDN в "right" совпадает с локальным IP адресом стороы меняются местами.
- конфиги dpd - Dead peer detection
- left/right - IP адрес, leftid/rightid - идентификатор, т.е. если клиент за натом в качестве leftid указываем адрес на интерфейсе
- leftsourceip=%config - клиент запросит у сервера виртуальный адрес
- с помощью настроек left/rightsubnet можно организовать split tunnel. В моей конфигурации на leftsubnet на сервере и rightsubnet на клиенте 0.0.0.0/0 т.е. весь трафик заворачивается в туннель


4. Логи.
4.1. Самый простой вариант: на любой стороне можно добавить в /etc/ipsec.conf
config setup
        charondebug="cfg 2, dmn 2, ike 2, net 1"


Тогда в /var/log/syslog будут писаться довольно подробные логи

4.2. Вообще, в strongswan достаточно гибгкий механизм логирования, можно использовать stdout/stderr, файл или syslog
По умолчанию, strongswan не может писать логи в файлы в Убунту (вероятно, эта же проблема не позволяет корректно перехватывать сообщения от strongswan из stderr).
Решение я нашел здесь:
http://tiebing.blogspot.com/2015/10/ubuntu-1404-strongswan-not-logging.html
It turns out that ubuntu uses "AppArmor" to limit where strongswan can write files. You can install apparmor-utils and use the command "aa-complain" to turn strongswan binaries from "enforce" mode to "complain" mode:

# apt-get install apparmor-utils
# aa-status
# aa-complain /usr/lib/ipsec/charon
Setting /usr/lib/ipsec/charon to complain mode.


После применения этого фикса, можно настроить логгирование в в /etc/strongswan.config. Пример (логи пишутся в stdout и /var/log/charon.log):
charon {
    load_modular = yes
    plugins {
        include strongswan.d/charon/*.conf
    }
    filelog {
                /var/log/charon.log {
                        append = no
                        default = 0
            ike = 1
            knl = 1
                        flush_line = yes
                }
        stdout {
            default = 0
            ike = 1
            knl = 1
        }
        }

}


5. Полезные команды:
-перечитать конфиги и перезапустить ipsec:
ipsec reload && ipsec restart

-включить/вылючить конкретное соединение (conn XXXX в ipsec.conf):
ipsec up/down XXXX

-перечитать настройки в ipsec.secrets:
ipsec rereadsecrets

6. Проще всего включать/выключать соединение на клиенте из консоли. Лично мне все графические клиенты показались неудобными.
Если конечный пользователь совсем не дружит с консолью, можно использовать вот этот простой скрипт на Python (для нормальной работы, требуется чтобы charon писал логи в /var/log/charon.log, см. пример выше):

#!/usr/bin/env python3

import subprocess
import time


def execute(cmd):
    popen = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    for out_line in popen.stdout:
        yield str(out_line)


started = False
for line in execute(['tail', '-n 1', '-F', '/var/log/charon.log']):
    #print(f'TEST:{line}')
    if not started:
        subprocess.Popen(['sudo', 'ipsec', 'up', 'VPN'], stdout=subprocess.PIPE)
        started = True
    if 'retransmit 2' in line:
        print("Connection timeout. Try again later")
        subprocess.run(['sudo', 'ipsec', 'down', 'VPN'], stdout=subprocess.PIPE)
        time.sleep(3)
        break
    if 'established with SPIs' in line:
        print('Connection established.')
        while True:
            try:
                run = input('Ctrl+C to terminate\n')
            except KeyboardInterrupt:
                print('\nClosing connection')
                subprocess.run(['sudo', 'ipsec', 'down', 'VPN'], stdout=subprocess.PIPE)
                time.sleep(3)
                break

Сервер strongswan ipsec + клиенты на Win10 и Ubuntu ч.3: Настройка клиента на Win10

Здесь все просто:

1. Создаем vpn подключение на клиентском ПК, включаем обязательное шифрование.




2. Импортируем корневой сертификат (caCert.der)в доверенные корневые центры сертификации локального компьютера.

3. Отключаем Split Tunnel на клиентском ПК, чтобы получить маршрут по умолчанию через VPN (Powershell):
Set-VpnConnection –Name 'Test' –SplitTunneling $false 

4. После очередного обновления strongswan пришлось подкрутить настройки VPN на Windows, чтобы при подключении использовались приемлемые для strongswan параметры: https://docs.microsoft.com/en-us/powershell/module/vpnclient/set-vpnconnectionipsecconfiguration?view=win10-ps  

Сервер strongswan ipsec + клиенты на Win10 и Ubuntu ч. 2: Настройка iptables на сервере

1. Перед настройкой IPtables запланировать перезагрузку через 10 минут, чтобы не потерять доступ, если что-то пойдет не так:

shutdown -t 10 –r

Отменить перезагрузку:
shutdown –c 

2. Создаем скрипт для iptables (не забываем chmod 0740)
nano /usr/local/firewall/firewall_static.sh

3. Правила:
#!/bin/sh

PATH='/sbin'
ALLOW_SSH='<ip_addresses>'
ALLOW_VPN='<ip_addresses>'
WAN='<int_name>'
IPSEC_NET='<network>'

# Flush previous rules, delete chains and reset counters
iptables -F
iptables -X
iptables -Z
iptables -t nat -F

# Default policies
iptables -P FORWARD DROP
iptables -P INPUT   DROP
iptables -P OUTPUT  DROP

echo -n '1' > /proc/sys/net/ipv4/ip_forward
echo -n '0' > /proc/sys/net/ipv4/conf/all/accept_source_route
echo -n '0' > /proc/sys/net/ipv4/conf/all/accept_redirects
echo -n '1' > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo -n '1' > /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses

# Enable loopback traffic
iptables -A INPUT  -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Enable statefull rules (after that, only need to allow NEW conections)
iptables -A INPUT   -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT


# Drop invalid state packets
iptables -A INPUT   -m conntrack --ctstate INVALID -j DROP
iptables -A OUTPUT  -m conntrack --ctstate INVALID -j DROP
iptables -A FORWARD -m conntrack --ctstate INVALID -j DROP

# Allow SSH management
iptables -A INPUT -i $WAN -s $ALLOW_SSH -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# Enable all outgoing traffic to internet
iptables -A OUTPUT -o $WAN -d 0.0.0.0/0 -j ACCEPT


#Allow incoming IKE connections
iptables -A INPUT -i $WAN -p esp -s $ALLOW_VPN -j ACCEPT
iptables -A INPUT -i $WAN -p ah -s $ALLOW_VPN -j ACCEPT
iptables -A INPUT -i $WAN -p udp -m udp --sport 500 --dport 500 -s $ALLOW_VPN -j ACCEPT
iptables -A INPUT -i $WAN -p udp -m udp --sport 4500 --dport 4500 -s $ALLOW_VPN -j ACCEPT

#Adjust TCP MSS
iptables -t mangle -I FORWARD -p tcp -m policy --pol ipsec --dir in --syn -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360

iptables -t mangle -I FORWARD -p tcp -m policy --pol ipsec --dir out --syn -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360


#Allow forwarding for VPN
iptables -A FORWARD -s $IPSEC_NET -d 0.0.0.0/0 -i $WAN -m policy --dir in --pol ipsec --reqid 1 --proto esp -j ACCEPT
iptables -A FORWARD -s $IPSEC_NET -d 0.0.0.0/0 -o $WAN -m policy --dir out --pol ipsec --reqid 1 --proto esp -j ACCEPT

#Configure NAT for VPN users
iptables -t nat -A POSTROUTING -s $IPSEC_NET -o $WAN -m policy --dir out --pol ipsec -j ACCEPT
iptables -t nat -A POSTROUTING -s $IPSEC_NET -o $WAN  -j MASQUERADE

## LOGGING to /var/log/messages
#iptables -A INPUT   -j LOG --log-level debug --log-prefix '[FW INPUT]:    '
#iptables -A OUTPUT  -j LOG --log-level debug --log-prefix '[FW OUTPUT]:   '
#iptables -A FORWARD -j LOG --log-level debug --log-prefix '[FW FORWARD ]: '


4. Создаем также правила для ipv6 в файле /usr/local/firewall/ipv6_firewall.sh
(не забываем chmod 0740)
#!/bin/sh
PATH='/sbin'

# Flush the tables to apply changes
ip6tables -F

#ACCEPT POLICY
ip6tables -P INPUT DROP #If it doesn't match a rule Drop it
ip6tables -P FORWARD DROP #NO ROUTING POLICY DROP
ip6tables -P OUTPUT ACCEPT #If it doesn't match a rule

########
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -m state --state ESTABLISHED,RELATED -A INPUT -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT

5. Добавляем . /usr/local/firewall/firewall_static.sh и ./usr/local/firewall/ipv6_firewall.sh
в /etc/rc.local перед exit0

6. Проверяем счетчики iptables
iptables -vL
iptables -t nat -L -n -v

7. Смотрим загрузку интерфейсов
iftop

вторник, 21 мая 2019 г.

Сервер strongswan ipsec + клиенты на Win10 и Ubuntu ч. 1: Настройка strongswan на сервере


Авторизация виндовых клиентов будет происходить по EAP, клиентов на Убунту - с помощью PSK.

1. Устанавливаем необходимые пакеты:
apt-get install strongswan libcharon-extra-plugins dnsmasq

Дополнительно для debian9: apt-get install strongswan-pki

2. Генерируем сертификаты. Можно пойти правильным путем и получить "честные" сертификаты у центра сертификации, типа Comodo. В данном случае вариант бюджетный - самоподписанные сертификаты. В принципе, они ничем не хуже, кроме того, что каждую клиентскую машину нужно настраивать вручную, для того, чтобы она доверяла нашей CA.

2.1 Закрытый ключ для CA
mkdir cert
cd cert
ipsec pki --gen > caKey.der


2.2 Генерируем самоподписанный сертификат CA
ipsec pki --self --in caKey.der --dn "C=CH, O=MyVPN, CN=MyVPN CA" --ca > caCert.der


2.3 Генерируем закрытый ключ сервера
ipsec pki --gen  > peerKey.der


2.4 Генерируем сертификат для сервера
ipsec pki --pub --in peerKey.der | ipsec pki --issue --flag serverAuth --san <server_IP_or_FQDN> --cacert caCert.der --cakey caKey.der \
--dn "C=CH, O=MyVPN, CN=MyVPNServer" > peerCert.der


*для Windows обязательный аргумент --san, он должен совпадать с реальным IP адресом сервера, или его FQDN

2.5 Копируем сгенерированные файлы в соответствующие директории:
/etc/ipsec.d/private/peerKey.der
хранит закрытый ключ узла. Загрузку данного ключа следует настроить в ipsec.secrets
/etc/ipsec.d/certs/peerCert.der
хранит end-entity сертификат узла. Следует указать в ipsec.conf чтобы использовать.
/etc/ipsec.d/cacerts/caCert.der 
хранит CA сертификат с помощь. которого были выпущены и подписаны клиентские сертификаы. Загружается автоматически.

3 Добавляем конфигурацию для клиентов на Windows:
3.1 В /etc/ipsec.conf:
conn win10
        dpdaction=clear
        dpddelay=35s
        dpdtimeout=300s
        fragmentation=yes
        rekey=no

        #left = server side
        left=%any
        leftsubnet=0.0.0.0/0
        leftcert=peerCert.der
        leftfirewall=yes
        leftsendcert=always

        right=%any
        rightsourceip=10.1.1.2/32
        rightdns=8.8.8.8
        eap_identity=%identity
        rightauth=eap-mschapv2
        keyexchange=ikev2
        auto=add


3.2 В /etc/ipsec.secrets
: RSA peerKey.der
test : EAP "abcd1234"


4 Добавляем конфиг для клиентов на Ubuntu: 
4.1 В /etc/ipsec.conf: 
conn ubnt
        dpdaction=restart
        dpddelay=35s
        dpdtimeout=300s
        rekey=no

        left=<public_ip>
        leftid=<public_ip>       
        leftsubnet=0.0.0.0/0
        leftfirewall=yes

        right=<public_ip>
        rightid=<private_ip>
        rightdns=8.8.8.8
        rightsourceip=10.1.1.3/32
        ike=aes256-sha2_256-modp1024!
        esp=aes256-sha2_256!

        authby=secret
        auto=add


4.2 В /etc/ipsec.secrets  
<client_ID> <server_ID> : PSK <key>

*в такой форме записи ключ указывается без кавычек! 

Некоторые комментарии:
 -в моем сценарии клиент за NAT-ом поэтому в качестве аргумента 'left' используется его публичный адрес, в качестве 'left id' - серый адрес.
 - leftfirewall=yes необходимо, если на сервере настроен NAT 
- rightsourceip - виртуальный адрес, который будет выдаваться клиенту. Можно указать целую подсеть, если клиентов много.

вторник, 13 июня 2017 г.

802.11ac



Very High Trhoughput (VHT). Только 5ГГц. До 6.933Гбит/с (до 1.3.Гбит/с для трех пространственных потоков). Модуляция до 256QAM, ширина канала до 160МГц, только explicit бимформинг, 10 возможных MCS, multiuser MIMO.

Может использоваться как один 160МГц канал, так и два 80МГц канала параллельно.

До восьми пространственных потоков на точку, до 4 на одно устройство.

Dynamic bandwidth: если на точке настроен канал 40МГц и шире, перед тем как передавать она проверяет занятость кажого 20МГц канала, и, если один или более заняты, использует только свободные. Т.о. точки ac могу адаптироваться к условиям среды, используя максимально широкий канал.

QAM256 - различные сочетания 16 сдвигов фаз и 16 сдвигов амплитуды. Каждое сочетание кодирует различные битовые последовательности.

В обозначении модуляций, например QAM256 5/6, вторая часть обозначает уровень кодирования, используемый для исправления ошибок. Первое число - количество бит пользовательских данных относительно числа бит в канале (второе число). Чем больше это отношение, тем выше пропускная способность, и тем меньше избыточности (например, при ширине канала 20МГц, QAM 256 3/4 позволяет добиться битрейта 86.7Мбит/с, а QAM256 5/6 - 96.3Мбис/с).

В ac убрана поддержка unequal modulation. Используется A-MPDU

Точки ac могут использоваться RTS/CTS фреймы для совместной работы в более широкой полосе. В основном (primary) 20МГц канале передается контрольный трафик. Если дополнительные каналы свободны, точка может использовать для передачи дополнительные 20МГц каналы, увеличивая тем самым пропускную способность.

Из соображений энергосбережения, многие мобильные устройства поддерживают только один поток (spatial stream). В связи с этим   MU-MIMO (multiuser) стремится к тому, чтобы передавать максимальное количество потоков, неважно для четрыхе клиентов, поддерживающих один потом, или одного клиента, поддерживающего четыре. Только downstream (от точки к клиенту).

Соответствующим образом работает multiuser бимформинг. Находящиеся поблизостои клиенты могут испытывать проблемы (помехи, создаваемые сигналами, направленными соседним устройствам). После того, как точка передала данные, она по очереди запрашивает у клиентов block ack (отправляя Block Acknowledgement Request).

При переходе на ac следует учитывать, что реальная скорость будет примерно 2/3 от максимально заявленной. Следует учитывать требования к PoE и пропускной способности аплинков. Также следует помнить, что многие устройства не поддерживающие 5ГГц будут неспособны подключиться к новой точке ac. Также следует принимать во внимание:
1. А нужно ли вообще переходить на ac, учитывая то, как ходит трафик в сети? Например, если только предоставляется доступ в интернет клиенстским устройствам, аплинк будет ниже, чем пропускная способность точки доступа
2. Если в сети используются одновременно устройства поддерживающие и не поддерживающие несколько пространстсвенных потоков, велика вероятность что производительность первых будет сильно снижена. Следует оценить а стоит ли полученный прирост пропускной способности затрат на переход.
3. Высокая пропускная способность MU-MIMO недостижима, если клиенты недостаточно разнесены в пространстве.

Обязательные требования Wi-Fi Alliance:
1. Ширина канала 20, 40, 80 МГц
2. MCS 0-7
3. Не менее двух пространственных потоков для точек и не менее одного для клиентов
4. Защитный интервал 800нс (400 - опционально)

Beamforming feedback, STBC, LDPC, MU-MIMO - опциональные требования.


D. Coleman, D. Wescott - Certified Wireless Network Administration Official Study Guide