
Предыстория
Недавно я взялся переводить межсетевой экран на своей РС с проверенных временем iptables на новенькие nftables. Для более углублённого изучения таблиц nf я поставил себе задачу: настроить прозрачный прокси-сервер (Squid) с разбором шифрованных соединений (HTTPS) для раздачи доступа в Интернет виртуальным машинам, РС «Raspberry Pi», а также своему смартфону (работающему с ОС «Android» 6-го выпуска) по беспроводному соединению (с помощью приложения hostapd).
Обозначения
| Буквы равной ширины | Приказы оболочки и содержимое конфигурационных файлов. | 
| Полужирные буквы | Настройки, строго необходимые для прозрачного посредничества. | 
| Наклонные буквы | Настройки, специфичные для моей установки (номера выпусков ПО, адреса канального и сетевого уровня, названия сетевых интерфейсов и т. п.). В вашем случае значения, как правило, будут другими. | 
| Подчёркнутые буквы | Настройки, необходимые для работы разбора шифрованных соединений | 
Дано
| Операционная система | «Gentoo Linux» со службой запуска служб «OpenRC». Все дальнейшие настройки будут применимы к этой поставке  | 
| Ядро | sys-kernel/gentoo-sources-5.3.1 USE="" Здесь и далее снятые USE-флаги не показаны  | 
| Прокси-сервер | net-proxy/squid-4.8 USE="caps ssl ssl-crtd"  | 
| Библиотека шифрования | dev-libs/openssl-1.1.1c-r1 USE=«asm test zlib»  | 
| Приложение nft | net-firewall/nftables-0.9.2 USE=«doc gmp modern_kernel»  | 
| Приложение ip | sys-apps/iproute2-5.2.0-r1 USE=«caps minimal»  | 
| Служба записи в журнал | app-admin/ulogd-2.0.7-r1 USE=«nfct nflog»  | 
Настройка ядра

[*] Networking support --->
 Networking options --->
 [*] TCP/IP networking
 [*] IP: advanced router
 [*] IP: policy routing
 [*] Network packet filtering framework (Netfilter) --->
 [*] Advanced netfilter configuration
 Core Netfilter Configuration --->
 # не обязательно, но пригодится для фильтрации пакетов на входе сетевых интерфейсов
 [*] Netfilter ingress support
 # не обязательно, но пригодится для отладки
 <*> Netfilter LOG over NFNETLINK interface
 <*> Netfilter connection tracking support
 <*> Netfilter nf_tables support
 <*> Netfilter nf_tables set infrastructure
 # не обязательно, но пригодится для фильтрации пакетов на входе сетевых интерфейсов
 [*] Netfilter nf_tables netdev tables support
 <*> Netfilter nf_tables conntrack module
 # не обязательно, но пригодится для отладки
 <*> Netfilter nf_tables counter module
 # не обязательно, но пригодится для отладки
 <*> Netfilter nf_tables log module
 <*> Netfilter nf_tables masquerade support
 <*> Netfilter nf_tables nat module
 <*> Netfilter nf_tables socket match support
 <*> Netfilter nf_tables tproxy support
 IP: Netfilter Configuration --->
 [*] IPv4 nf_tables support
 # не обязательно, но пригодится для фильтрации пакетов на канальном уровне
 <*> Ethernet Bridge nf_tables support --->
Для справки привожу выдержку из /usr/src/linux/.config:
CONFIG_NET=y
CONFIG_INET=y
<b>CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y</b>
CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_NETLINK_LOG=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_TABLES=y
CONFIG_NF_TABLES_SET=y
CONFIG_NF_TABLES_NETDEV=y
CONFIG_NFT_CT=y
CONFIG_NFT_COUNTER=y
CONFIG_NFT_LOG=y
CONFIG_NFT_MASQ=y
CONFIG_NFT_NAT=y
<b>CONFIG_NFT_SOCKET=y
CONFIG_NFT_TPROXY=y</b>
CONFIG_NF_TABLES_BRIDGE=y
Настройка сети
Если служба net.lo не добавлена в уровень выполнения «boot», то её следует туда добавить:
rc-config add net.lo bootПодобным же образом созданы и настроены на запуск для уровня выполнения «default» службы net.br0 (мост для виртуальных машин и смартфона), net.enp0s25 (проводной интерфейс) и net.wlp3s0 (беспроводной интерфейс), например:
ln -s net.lo /etc/init.d/net.br0
rc-config add net.br0 default
Итоговый конфигурационный файл /etc/conf.d/net в нашем примере выглядит так (за вычетом не относящихся к нашей задаче настроек):

# TProxy
routes_lo='local default dev lo table 3128'
# Qemu bridge
bridge_force_br0=''
mac_br0='XX:XX:XX:XX:XX:XX'
config_br0='192.168.120.1/24'
# Ethernet
config_enp0s25='dhcp'
modules_enp0s25='udhcpc'
dhcp_enp0s25='release nontp'
udhcpc_enp0s25='--retries 8 --timeout 10'
fallback_enp0s25='10.a.b.c/16'
fallback_routes_enp0s25='default via 10.a.0.1'
# Wi-Fi
if [[ -f /var/lib/misc/hostapd ]]; then
  modules_wlp3s0="!ifconfig !iwconfig !wpa_supplicant"
  config_wlp3s0='null'
else
  config_wlp3s0='dhcp'
  modules_wlp3s0='udhcpc'
  wpa_supplicant_wlp3s0='-Dnl80211'
fi
postup() {
  if [ "${IFACE}" == lo ]; then
    ip rule add fwmark 3128 lookup 3128
  fi
  return 0
}
Выделенные строки добавляют новую таблицу маршрутизации, в данном примере под номером 3128, и ворота — по умолчанию для неё (интерфейс «loopback»), и правило — по которому пакеты, помеченные межсетевым экраном меткой номер 3128 (десятичные числа в обоих случаях), будут обслуживаться этим расписанием.
Чтобы направляемые пакеты не были отброшены из-за несоответствия адресов сетевого уровня (при прозрачном проксировании пакеты сохраняются в первозданном виде!) необходимо добавить в /etc/sysctl.conf следующие строки (или изменить уже имеющиеся):

Если нужно применить эти настройки до перезагрузки, то следует дополнительно задать их для обоих сетевых интерфейсов с доступом в Интернет:
sysctl net.ipv4.conf.enp0s25.rp_filter=0
sysctl net.ipv4.conf.wlp3s0.rp_filter=0Настройка прокси-сервера
Поскольку обычный (непрозрачный) порт прокси-сервера у нас будет закреплён на адресе моста (192.168.120.1), добавим следующую строку в /etc/rc.conf:
rc_squid_need="net.br0"Следующие настройки прокси-сервера в рамках этой статьи рассмотрены не будут:
- Проверка личности пользователей на обычном (непрозрачном) порту;
 - ICAP для объединения с устройством предотвращения утечек данных (например, InfoWatch Traffic Monitor);
 - Выработка ключей шифрования и создание сертификата.
 
Конфигурационный файл /etc/squid/squid.conf в итоге выглядит так (на всякий случай привожу полностью):


	# Задаём перечень виртуальных машин
1	acl virtual_machines src 192.168.120.0/24
2	acl SSL_ports port 443
	# Пример добавления необычного для соединений HTTPS порта
3	acl SSL_ports port 1012        # для badssl.com
	# Пример добавления необычного для соединений HTTPS порта
4	acl SSL_ports port 33443       # getcourse.ru для artlinerschool.ru
5	acl Safe_ports port 21         # ftp
6	acl Safe_ports port 80         # http
7	acl Safe_ports port 443        # https
	# Пример добавления необычного привилегированного порта
8	acl Safe_ports port 1012       # для badssl.com
9	acl Safe_ports port 1025-65535 # непривилегированные порты
10	acl CONNECT method CONNECT 
11	http_access deny !Safe_ports
12	http_access deny CONNECT !SSL_ports
13	http_access allow localhost manager
14	http_access deny manager
15	http_access allow localhost
	# Разрешаем подключение виртуальных машин к прокси-серверу
16	http_access allow virtual_machines
17	http_access deny all
	# Настраиваем обычный (непрозрачный) порт. Используем адрес моста, на случай прямого подключения виртуальных машин (например, как к прокси-серверу FTP)
18	http_port 192.168.120.1:3128 ssl-bump options=ALL:NO_SSLv3:NO_TLSv1 cert=/etc/squid/squid.pem
	# Настраиваем прозрачный порт для нешифрованных соединений. Тут используем адрес интерфейса «loopback», поскольку на него указывает таблица маршрутизации под номером 3128, настроенное ранее, и на него же будут указывать правила межсетевого экрана
19	http_port 127.0.0.1:3129 tproxy
	# Настраиваем прозрачный порты для шифрованных соединений. Тут используем адрес интерфейса «loopback», поскольку на него указывает таблица маршрутизации под номером 3128, настроенное ранее, и на него же будут указывать правила межсетевого экрана
20	https_port 127.0.0.1:3130 tproxy ssl-bump options=ALL:NO_SSLv3:NO_TLSv1 cert=/etc/squid/squid.pem
	# прокси-сервер выходит в сеть напрямую, без других прокси-серверов
21	always_direct allow all
	# Задаём перечень проверенных страниц, имеющим самоподписанный сертификат
22	acl BrokenButTrustedServers dstdomain "/etc/squid/selfsigned.txt"
	# Разрешаем подключение только к проверенным страницам, имеющим самоподписанный сертификат
23	sslproxy_cert_error allow BrokenButTrustedServers
24	sslproxy_cert_error deny all
	# Для безопасности разрешаем только свежайшие выпуски TLS
25	tls_outgoing_options min-version=1.2
	# Задаём перечень непотребных страниц
26	acl blocked ssl::server_name "/etc/squid/blocked_domains.txt"
	# Задаём перечень страниц, которые перестают работать из-за подмены сертификата (в первую очередь это касается виртуальных частных сетей на основе SSL)
27	acl fragile dstdomain "/etc/squid/fragile_domains.txt"
28	acl step1 at_step SslBump1
29	ssl_bump peek step1
	# Запрещаем подключения к непотребным страницам
30	ssl_bump terminate blocked
	# Делаем исключения из разбора шифрования для страниц, которые перестают работать из-за подмены сертификата
31	ssl_bump splice fragile
	# Все остальные шифрованные соединения разбираем, подменяя сертификата
32	ssl_bump bump all
	# Настраиваем хранилище подменных сертификатов
33	sslcrtd_program /usr/libexec/squid/security_file_certgen -s /var/lib/squid/ssl -M 4MB
34	cache_dir rock /var/cache/squid-r 512 max-size=32768
35	cache_dir aufs /var/cache/squid 512 64 1024 min-size=32768
36	coredump_dir /var/tmp/squid
37	refresh_pattern    ^ftp:          1440 20% 10080
38	refresh_pattern -i (/cgi-bin/|\?) 0    0%  0
39	refresh_pattern    .              0    20% 4320
40	memory_replacement_policy heap GDSF
41	cache_replacement_policy LFUDA
42	maximum_object_size 32 MB
43	logfile_rotate 3
44	debug_options ALL,1,rotate=3
45	cache_mem 512 MB
46	visible_hostname host.shadow.amn
47	udp_incoming_address 127.0.0.1
48	pinger_enable off
Настройка межсетевого экрана
Настроим запуск на уровне выполнения «default» служб nftables и ulogd (последняя нужна для уведомления о пакетах):
rc-config add nftables default
rc-config add ulogd defaultПоскольку в настройках межсетевого экрана будет присутствовать мост, добавим следующую строку в /etc/rc.conf:
rc_nftables_need="net.br0"Для работы уведомления в /etc/sysctl.conf необходимо добавить следующую строку:
net.netfilter.nf_log.2 = nfnetlink_logЧтобы конфигурационный файл находился в папке /etc/nftables, внесём такое изменение в /etc/conf.d/nftables:
NFTABLES_SAVE="/etc/nftables/rules-save"Чтобы временные изменения не сохранялись в конфигурационном файле, внесём ещё одно изменение в /etc/conf.d/nftables:
SAVE_ON_STOP="no"Опишу задачи, поставленные перед межсетевым экраном:
- Правила по умолчанию во всех цепочках таблицы ip filter должны пакеты удалять (даже в цепочке output!). Аналогично для таблиц netdev filter;
 - Обмен любого вида, кроме IPv4 и относящегося к нему служебного обмена (например, ARP), пресекается насколько возможно раньше (ни IPv4, ни IPSec не используются);
 - Многоадресные пакеты IPv4 также удаляются насколько возможно раньше;
 - Для защиты Android-смартфона (при подключении к мосту с помощью приложения hostapd) широковещательный обмен, производимый виртуальными машинами работающими под управлением ОС «Microsoft Windows», не должен передаваться на беспроводной интерфейс.
 - Пользоваться нашим Wi-Fi можно только устройствами с известными MAC-адресами.
 
Конфигурационный файл /etc/nftables/rules-save в итоге выглядит так (за вычетом большинства пояснений):






1	#!/sbin/nft -f
	# Задаём переменные, которые будут использоваться в правилах
2	define icmp_types = { destination-unreachable, time-exceeded, parameter-problem, echo-request, echo-reply }
3	define host = 192.168.120.1
4	define br = br0
5	define my_br_mac = XX:XX:XX:XX:XX:XX
6	define eth = enp0s25
7	define my_eth_mac = YY:YY:YY:YY:YY:YY
8	define wifi = wlp3s0
9	define my_wifi_mac = WW:WW:WW:WW:WW:WW
10	define my_phone = TT:TT:TT:TT:TT:TT
11	define virtual_machines = 192.168.120.0/24
12	define privileged_vm = { 192.168.120.22, 192.168.120.129 }
13	define dhcp_client = 192.168.120.224/27
14	define transmission_port = 51413
15	define no_track = { microsoft-ds, ms-wbt-server }
16	define vm_ssh = 192.168.120.70
17	define infowatch_pc = { 10.a.0.0/16, 10.h.0.0/16 }
18	define infowatch_my = 10.a.b.c
19	define squid_normal = 3128
20	define squid_transp = 3129
21	define squid_trassl = 3130
22	define sslvpn.infowatch.com = 46.148.194.86
23	define files.infowatch.ru = 178.16.25.15
24	define iwprint.infowatch.ru = 10.d.e.f
25	define s163.getcourses.ru = 95.213.153.163
26	define tls-v1-2.badssl.com = 104.154.89.105
27	flush ruleset
28	table ip raw {
29	  chain prerouting {
30	    type filter hook prerouting priority -300;
	    # Пытаемся облегчить работу межсетевого экрана тем, что соединения с самым большим объёмом пакетов отслеживаться не будут
31	    meta l4proto { tcp, udp } th dport $transmission_port notrack
32	    tcp sport $no_track ip saddr != $iwprint.infowatch.ru notrack
33	    ip saddr { $sslvpn.infowatch.com, $files.infowatch.ru } tcp sport https notrack
34	  }
35	}
36	table ip filter {
37	  chain input {
38	    type filter hook input priority 0; policy drop;
	    # Поскольку в этой цепочке правило по умолчанию удаляет пакеты, то необходимо разрешить все пакеты на интерфейс «loopback»
39	    iif lo accept
	    # Разрешаем пакеты ICMP только необходимых видов для обхода возможных уязвимостей, связанных с редкими и неиспользуемыми видами ICMP
40	    icmp type $icmp_types accept
	    # Удаляем битые пакеты
41	    ct state invalid counter drop
	    # Обход падения ядра, связанного с избирательным подтверждением (SACK) пакетов TCP. Падения эти уже устранены в свежих выпусках ядра, но данное правило оставлено на всякий случай
42	    tcp flags syn tcp option maxseg size < 999 counter drop
	    # Полностью разрешаем Bittorrent, поскольку мы исключили его из отслеживания в строке 31
43	    iif $eth meta l4proto { tcp, udp } th dport $transmission_port accept
	    # Удаляем пакеты, начинающие соединение, и заносим о них запись в дннвник, если они пришли с неотслеживаемых соединений
44	    tcp flags & (syn | ack) == syn ct state untracked log prefix "Untracked:" group 2 counter counter drop
	    # Разрешаем пакеты с портов, которые мы исключили из отслеживания в строке 32
45	    tcp sport $no_track accept
	    # Разрешаем пакеты с адресов, которые мы исключили из отслеживания в строке 33
46	    ip saddr { $sslvpn.infowatch.com, $files.infowatch.ru } tcp sport https accept
	    # Разрешаем пакеты от виртуальных машин, помеченные меткой 3128 (десятичное число)
47	    iif $br ip saddr $virtual_machines mark set 3128 counter accept
	    # Разрешаем виртуальным машинам подключаться к некоторым службам, в том числе к обычному (непрозрачному) порту прокси-сервера
48	    iif $br ip daddr $host ip saddr $virtual_machines tcp dport { domain, http, microsoft-ds, nfs, $squid_normal } accept
	    # Разрешаем все законные отслеженные соединения
49	    ct state { established, related } accept
	    # Разрешаем виртуальным машинам подключаться к некоторым службам, подразумевающим широковещательный обмен
50	    iif $br udp dport { domain, bootps, tftp, 4011 } counter accept
	    # Производим подсчёт удалённых пакетов, так как следующим правилом будет правило по умолчанию, удаляющее пакеты (см. строку 38)
51	    counter comment "Считаем выброшенные пакеты"
52	  }
53	  chain output {
54	    type filter hook output priority 100; policy drop;
	    # Поскольку в этой цепочке правило по умолчанию удаляет пакеты, то необходимо разрешить все пакеты со интерфейса «loopback»
55	    oif lo accept
	    # Разрешаем пакеты ICMP только необходимых видов для обхода возможных уязвимостей, связанных с редкими и неиспользуемыми видами ICMP
56	    icmp type $icmp_types counter accept
	    # Разрешаем службам отправлять пакеты виртуальным машинам с привилегированных портов (сравните со строками 48 и 50)
57	    oif { $eth, $wifi } udp dport . udp sport { bootps . bootpc } counter accept
58	    oif $br ip saddr $host ip daddr { $dhcp_client, 255.255.255.255 } udp sport . udp dport { bootps . bootpc } counter accept
59	    oif $br ip saddr $host ip daddr $virtual_machines udp sport { domain, tftp } counter accept
60	    oif $br ip saddr $host ip daddr $virtual_machines tcp sport { domain, http, microsoft-ds } accept
	    # Разрешаем прокси-серверу отправлять пакеты потребителям от имени страниц всемирной паутины с привилегированных портов. Если используется необычный порт для HTTPS вне привилегированного промежутка, то он подпадёт под следующее правило и его указывать здесь не нужно
61	    oif $br ip daddr $virtual_machines tcp sport { http, https, 1012 } counter accept
	    # Разрешаем отправку любых пакетов с портов, имеющих номера вне привилегированного промежутка, то есть выше 1024
62	    meta l4proto { tcp, udp } th sport >= 1025 accept
	    # Производим подсчёт удалённых пакетов, так как следующим правилом будет правило по умолчанию, удаляющее пакеты (см. строку 54)
63	    counter comment "Считаем выброшенные пакеты"
64	  }
65	  chain forward {
66	    type filter hook forward priority 0; policy drop;
	    # Помогаем виртуальным машинам с настройкой размера пакетов (MTU)
67	    tcp flags syn tcp option maxseg size set rt mtu counter
	    # Запрещаем виртуальным машинам обращаться к чужим службам разрешения имён
68	    iif $br ip daddr != $host meta l4proto { tcp, udp } th dport domain drop
	    # Разрешаем обмен с внешним миром (помимо прокси-сервера) только некоторым виртуальным машинам и всем, получившим временный адрес сетевого уровня, как правило, это будет смартфон. Эти правила не означают, что подключение ко всемирной паутине (порты 80 и 443) произойдёт для них без прокси-сервера, так как цепочка divert имеет более высокое первенство по сравнению с цепочкой forward (сравните строки 66 и 81). Кроме того, в строке 96 мы не преобразуем адрес сетевого уровня, если номер порта назначения равен 80 или 443
69	    iif $br ip saddr { $privileged_vm, $dhcp_client } accept
70	    oif $br ip daddr { $privileged_vm, $dhcp_client } accept
	    # Производим подсчёт удалённых пакетов, так как следующим правилом будет правило по умолчанию, удаляющее пакеты (см. строку 66)
71	    counter comment "Считаем выброшенные пакеты"
72	  }
	  # Создаём набор пар «адрес канального уровня • порт» для случаев использования соединениями HTTPS номеров портов, отличающихся от 443
73	  set nonstandard_https {
74	    type ipv4_addr . inet_service;
75	    elements = {
76	      $s163.getcourses.ru . 33443, # для страницы artlinerschool.ru
77	      $tls-v1-2.badssl.com . 1012, # для страницы badssl.com
78	  }
79	}
80	  chain divert {
81	    type filter hook prerouting priority -150; policy accept;
	    # Помечаем меткой 3128 (дес. ч.) все пакеты TCP, отправляющиеся из сокета, имеющего свойство прозрачности (свойство задаётся прокси-сервером)
82	    meta l4proto tcp socket transparent 1 mark set 3128 accept
	    # Помечаем меткой 3128 (дес. ч.) все пакеты TCP с портом назначения, имеющим номер 80. Одновременно заворачиваем их на прозрачного прокси-сервера
83	    ip daddr != { 127.0.0.1, $host } tcp dport http tproxy to 127.0.0.1:$squid_transp mark set 3128 counter accept
	    # Помечаем меткой 3128 (дес. ч.) все пакеты TCP с портом назначения, имеющим номер 443. Одновременно заворачиваем их на прозрачного прокси-сервера
84	    ip daddr != { 127.0.0.1, $host } tcp dport https tproxy to 127.0.0.1:$squid_trassl mark set 3128 counter accept
	    #  Помечаем меткой 3128 (дес. ч.) все пакеты TCP с адресами и портами назначения из набора nonstandard_https (см. строки 76 и 77 для примера). Одновременно заворачиваем их на прозрачного прокси-сервера
85	    ip daddr . tcp dport @nonstandard_https tproxy to 127.0.0.1:$squid_trassl mark set 3128 counter accept
86	  }
87	}
88	table ip nat {
89	  chain prerouting {
90	    type nat hook prerouting priority 0; policy accept;
	    # Разрешаем другим РС из рабочей сети подключаться к одной из виртуальных машин с помощью SSH
91	    iif $eth ip daddr $infowatch_my ip saddr $infowatch_pc tcp dport ssh counter dnat $vm_ssh
92	  }
93	  chain postrouting {
94	    type nat hook postrouting priority 100; policy accept;
	    # Преобразуем адреса сетевого уровня в пакетах, отправляемых вовне прокси-сервером, так как он отправляет их от лица виртуальных машин. Принадлежность прокси-серверу определяем с помощью свойств UID и GID сокета
95	    oif { $eth, $wifi } ip saddr $virtual_machines skuid . skgid { squid . squid } counter masquerade
	    # Преобразуем адреса сетевого уровня в пакетах, отправляемых вовне некоторыми виртуальными машинами, и всеми, получившими временный адрес сетевого уровня, (сравните со строками 69 и 70). При этом ведём им учёт, занося в общий журнал, с целью выявления необычных для соединений HTTPS портов. После выявления таковых заносим их вместе с адресами в набор nonstandard_https (см. строки 76 и 77 для примера).
96	    oif { $eth, $wifi } ip saddr { $privileged_vm, $dhcp_client } tcp dport != { http, https } log prefix "NAT:" group 2 counter masquerade
97	  }
98	}
	
99	table bridge filter {
  # Решаем задачу №5: Разрешаем передавать данные нашему Wi-Fi только известным устройствам
100	  chain input {
    type filter hook input priority -200; policy accept;
    iif $wifi ether saddr != $my_phone counter drop
  }
  # Решаем задачу №4: защита смартфона от всего, не связанного с IPv4, и от ненужных ему широковещательных рассылок
  chain forward {
101	    type filter hook forward priority -200; policy accept;
102	    oif $wifi ether type arp accept
103	    oif $wifi ip protocol { icmp, tcp, udp } ip daddr != 192.168.120.255 accept
104	    oif $wifi drop
105	  }
  # Решаем задачу №5: Разрешаем нашему Wi-Fi отдавать данные только известным устройствам
106	  chain output {
    type filter hook input priority 200; policy accept;
    oif $wifi ether daddr != $my_phone counter drop
  }
}
	# Решаем задачу №2: удаление на входах интерфейсов всего, не связанного с IPv4
107	table netdev filter {
108	  chain enp0s25 {
109	    type filter hook ingress device enp0s25 priority 0; policy drop;
110	    ether type arp accept
111	    ether daddr $my_eth_mac ip protocol { icmp, tcp, udp, gre } accept
112	  }
113	  chain wlp3s0 {
114	    type filter hook ingress device wlp3s0 priority 0; policy drop;
	    # Разрешаем ARP и EAPOL на случай, когда подключение к Интернету происходит через беспроводной интерфейс
115	    ether type { arp, 0x888e } accept
	    # Поскольку беспроводный интерфейс будет подключаться к мосту, здесь необходимо указать адреса канального уровня как самого интерфейса, так и моста
116	    ether daddr { $my_br_mac, $my_wifi_mac, ff:ff:ff:ff:ff:ff } ip protocol { icmp, tcp, udp, gre } accept
117	  }
118	}
Настройка потребителей
На самой РС
Для более основательных испытаний прозрачного прокси-сервера я решил использовать его и для всех приложений (за некоторыми исключениями, о чём дальше) на самой РС.
Добавим сертификат прокси-сервера в общее хранилище:
mkdir -p /usr/local/share/ca-certificates
cp /etc/squid/squid.pem /usr/local/share/ca-certificates/squid.crtОбновим хранилище:
update-ca-certificatesПриложения — веб-браузеры «Firefox» и «Chromium» не используют общее хранилище сертификатов, поэтому его следует добавлять в соответствующие хранилища этих приложений.
Создадим конфигурационный файл /etc/env.d/38proxy с такими строками:
http_proxy=http://192.168.120.1:3128
https_proxy=http://192.168.120.1:3128
ftp_proxy=http://192.168.120.1:3128
Обновим переменные окружения:
env-updateПосле повторного входа настройки будут применены для всех приложений.
Об исключениях:
- На всякий случай оставим веб-браузер «Chromium», он будет всегда подключаться к сети напрямую, без прокси-сервера, для этого конфигурационный файл /etc/chromium/default изменим таким образом: 
CHROMIUM_FLAGS="--enable-seccomp-sandbox —no-proxy-server" - Приложение xfreerdp при наличии переменной окружения https_proxy пытается подключаться через прокси-сервера, поэтому в конфигурационный файл оболочки добавим следующую строку: 
alias xfreerdp='https_proxy= xfreerdp' - Приложение youtube-dl не может проверить сертификат, вероятно, из-за особенностей хранилища сертификатов языка Python. Постоянное решение пока не найдено, поэтому в конфигурационный файл оболочки добавим следующую строку:
alias youtube-dl='youtube-dl --no-check-certificate' 
На виртуальных машинах с ОС «Red Hat Enterprise Linux» 6-го и 7-го выпуска
На виртуальной машине включаем работу с сертификатами PEM:
update-ca-trust force-enableПереписываем с РС сертификат прокси-сервера на виртуальную машину:
scp squid.crt root@192.168.120.66:/etc/pki/ca-trust/source/anchors/На виртуальной машине обновляем сертификата:
update-ca-trust extractНа виртуальных машинах с ОС «Microsoft Windows» разных выпусков
Сертификат загружается в общее хранилище сертификатов машины (не пользователя!) в раздел «Доверенные корневые...». Веб-браузер «Firefox» не использует общее хранилище сертификатов, поэтому сертификат следует добавлять в соответствующее хранилище этого приложения.
На РС «Raspberry Pi» с ОС «Raspbian»
Обновление приложений прошло успешно без установки сертификата.
На смартфонах с ОС «Android»
Сертификат предварительно загружается на устройство, затем устанавливается с помощью приложения по управлению сертификатами. После этого у пользователя будет запрошено усиление безопасности входа в устройство (если это ещё не сделано) с помощью графического ключа или пароля.
Вывод
Новый брандмауэр в линуксе (nft) представляет собой прекрасный образчик свободного ПО, хорошо сочетающийся со Squid’ом, де-факто стандартом свободного прокси-сервера.
Первоисточники
1. http://wiki.squid-cache.org/Features/Tproxy4
2. /usr/src/linux/Documentation/networking/tproxy.txt
3. http://wiki.nftables.org
4. nft(8)
5. https://www.bounca.org/tutorials/install_root_certificate.html
Автор: Шамиль Саитов Nikodim_Tychoblin
          
 
click0
А вы не хотели бы переделать картинки с текстом на просто текст?
В очень крайнем случае, приложить в конце поста ссылку на pdf файл с вашим любимым и обязательным форматированием текста.
Nikodim_Tychoblin
Просто текст есть под картинками, скрытый в ссылке