mirror of https://github.com/bol-van/zapret/
2 changed files with 703 additions and 476 deletions
@ -0,0 +1,703 @@ |
|||
# Настройка BSD-подобных систем |
|||
|
|||
|
|||
## Поддерживаемые версии |
|||
**FreeBSD** 11.x+ , **OpenBSD** 6.x+, частично **MacOS Sierra +** |
|||
|
|||
> [!CAUTION] |
|||
> На более старых может собираться, может не собираться, может работать или не |
|||
> работать. На **FreeBSD** 10 собирается и работает `dvtws`. С `tpws` есть |
|||
> проблемы из-за слишком старой версии компилятора clang. Вероятно, будет |
|||
> работать, если обновить компилятор. Возможна прикрутка к последним версиям |
|||
> pfsense без веб интерфейса в ручном режиме через консоль. |
|||
|
|||
|
|||
## Особенности BSD систем |
|||
### Отсутствие nfqueue |
|||
В **BSD** нет `nfqueue`. Похожий механизм - *divert sockets*. Из каталога |
|||
**nfq** под **BSD** собирается `dvtws` вместо `nfqws`. Он разделяет с `nfqws` |
|||
большую часть кода и почти совпадает по параметрам командной строки. |
|||
|
|||
### Типы Firewall |
|||
**FreeBSD** содержит 3 фаервола : **IPFilter**, **ipfw** и **Packet Filter (PF |
|||
в дальнейшем)**. **OpenBSD** содержит только **PF**. |
|||
|
|||
### Сборка |
|||
Под **FreeBSD** `tpws` и `dvtws` собираются через `make`. |
|||
|
|||
Под **OpenBSD**: |
|||
```sh |
|||
make bsd |
|||
``` |
|||
|
|||
Под **MacOS**: |
|||
```sh |
|||
make mac |
|||
``` |
|||
|
|||
**FreeBSD** make распознает *BSDmakefile*, **OpenBSD** и **MacOS** - нет. |
|||
Поэтому там используется отдельный *target* в *Makefile*. Сборка всех |
|||
исходников: |
|||
```sh |
|||
make -C /opt/zapret |
|||
``` |
|||
|
|||
### Divert сокеты |
|||
*Divert сокет* это внутренний тип сокета ядра **BSD**. Он не привязывается ни к |
|||
какому сетевому адресу, не участвует в обмене данными через сеть и |
|||
идентифицируется по номеру порта `1..65535`. Аналогия с номером очереди |
|||
`NFQUEUE`. На *divert сокеты* заворачивается трафик посредством правил **ipfw** |
|||
или **PF**. Если в фаерволе есть *правило divert*, но на *divert порту* никто |
|||
не слушает, то пакеты дропаются. Это поведение аналогично правилам `NFQUEUE` |
|||
без параметра `--queue-bypass`. На **FreeBSD** *divert сокеты* могут быть |
|||
только **ipv4**, хотя на них принимаются и **ipv4**, и **ipv6** фреймы. На |
|||
**OpenBSD** *divert сокеты* создаются отдельно для **ipv4** и **ipv6** и |
|||
работают только с одной версией `ip` каждый. На **MacOS** похоже, что *divert |
|||
сокеты* из ядра вырезаны. См подробнее раздел про **MacOS**. Отсылка в *divert |
|||
сокет* работает аналогично отсылке через *raw socket* на linux. Передается |
|||
полностью IP фрейм, начиная с ip загловка. Эти особенности учитываются в |
|||
`dvtws`. |
|||
|
|||
### Lookup Tables |
|||
Скрипты `ipset/*.sh` при наличии **ipfw** работают с *ipfw lookup tables*. Это |
|||
прямой аналог **ipset**. *lookup tables* не разделены на **v4** и **v6**. Они |
|||
могут содержать **v4** и **v6** адреса и подсети одновременно. Если **ipfw** |
|||
отсутствует, то действие зависит от переменной `LISTS_RELOAD` в *config*. Если |
|||
она задана, то выполняется команда из `LISTS_RELOAD`. В противном случае не |
|||
делается ничего. Если `LISTS_RELOAD=-`, то заполнение таблиц отключается даже |
|||
при наличии **ipfw**. |
|||
|
|||
### PF с файла |
|||
**PF** может загружать ip таблицы из файла. Чтобы использовать эту возможность |
|||
следует отключить сжатие gzip для листов через параметр файла *config* |
|||
`GZIP_LISTS=0`. |
|||
|
|||
### Отсутствие splice |
|||
**BSD** не содержит системного вызова splice. `tpws` работает через переброску |
|||
данных в *user mode* в оба конца. Это медленнее, но не критически. Управление |
|||
асинхронными сокетами в `tpws` основано на linux-specific механизме *epoll*. В |
|||
**BSD** для его эмуляции используется *epoll-shim* - прослойка для эмуляции |
|||
*epoll* на базе *kqueue*. |
|||
|
|||
### mdig, ip2net |
|||
mdig и ip2net полностью работоспособны в **BSD**. В них нет ничего |
|||
системо-зависимого. |
|||
|
|||
|
|||
## FreeBSD |
|||
### Подгрузка ipdivert |
|||
*Divert сокеты* требуют специального модуля ядра - `ipdivert`. |
|||
|
|||
- Поместите следующие строки в `/boot/loader.conf` (создать, если отсутствует): |
|||
``` |
|||
ipdivert_load="YES" |
|||
net.inet.ip.fw.default_to_accept=1 |
|||
``` |
|||
|
|||
- `/etc/rc.conf`: |
|||
``` |
|||
firewall_enable="YES" |
|||
firewall_script="/etc/rc.firewall.my" |
|||
``` |
|||
|
|||
- `/etc/rc.firewall.my`: |
|||
```sh |
|||
$ ipfw -q -f flush |
|||
``` |
|||
|
|||
### Авто-восстановление правил ipfw и работа в фоне |
|||
В `/etc/rc.firewall.my` можно дописывать правила **ipfw**, чтобы они |
|||
восстанавливались после перезагрузки. Оттуда же можно запускать и демоны |
|||
zapret, добавив в параметры `--daemon`. Например так: |
|||
```sh |
|||
$ pkill ^dvtws$ |
|||
$ /opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2 |
|||
``` |
|||
|
|||
Для перезапуска фаервола и демонов достаточно будет сделать: |
|||
```sh |
|||
$ /etc/rc.d/ipfw restart |
|||
``` |
|||
|
|||
### tpws в прозрачном режиме |
|||
Краткая инструкция по запуску `tpws` в прозрачном режиме. |
|||
|
|||
> [!NOTE] |
|||
> Предполагается, что интерфейс **LAN** называется `em1`, **WAN** - `em0`. |
|||
|
|||
#### Весь трафик |
|||
```sh |
|||
$ ipfw delete 100 |
|||
$ ipfw add 100 fwd 127.0.0.1,988 tcp from me to any 80,443 proto ip4 xmit em0 not uid daemon |
|||
$ ipfw add 100 fwd ::1,988 tcp from me to any 80,443 proto ip6 xmit em0 not uid daemon |
|||
$ ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1 |
|||
$ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 |
|||
$ /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 |
|||
``` |
|||
|
|||
#### Трафик только на таблицу zapret |
|||
> За исключением таблицы nozapret |
|||
|
|||
```sh |
|||
$ ipfw delete 100 |
|||
$ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 |
|||
$ ipfw add 100 fwd 127.0.0.1,988 tcp from me to table\(zapret\) 80,443 proto ip4 xmit em0 not uid daemon |
|||
$ ipfw add 100 fwd ::1,988 tcp from me to table\(zapret\) 80,443 proto ip6 xmit em0 not uid daemon |
|||
$ ipfw add 100 allow tcp from any to table\(nozapret\) 80,443 recv em1 |
|||
$ ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1 |
|||
$ ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 |
|||
$ /opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 |
|||
``` |
|||
|
|||
> [!NOTE] |
|||
> Таблицы zapret, nozapret, ipban создаются скриптами из ipset по аналогии с |
|||
> Linux. Обновление скриптов можно забить в `cron` под root: |
|||
> ```sh |
|||
> $ crontab -e |
|||
> ``` |
|||
> |
|||
> ``` |
|||
> <...> |
|||
> 0 12 */2 * * /opt/zapret/ipset/get_config.sh |
|||
> ``` |
|||
|
|||
> [!CAUTION] |
|||
> При использовании **ipfw** `tpws` не требует повышенных привилегий для |
|||
> реализации прозрачного режима. Однако, без рута невозможен бинд на порты |
|||
> <1024 и смена UID/GID. Без смены UID будет рекурсия, поэтому правила **ipfw** |
|||
> нужно создавать с учетом UID, под которым работает `tpws`. Переадресация на |
|||
> порты >=1024 может создать угрозу перехвата трафика непривилегированным |
|||
> процессом, если вдруг `tpws` не запущен. |
|||
|
|||
|
|||
### Запуск `dvtws` |
|||
|
|||
#### Весь трафик |
|||
```sh |
|||
$ ipfw delete 100 |
|||
$ ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0 |
|||
# required for autottl mode only |
|||
$ ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted recv em0 |
|||
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 |
|||
``` |
|||
|
|||
#### Трафик только на таблицу zapret |
|||
> За исключением таблицы nozapret |
|||
|
|||
```sh |
|||
$ ipfw delete 100 |
|||
$ ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 |
|||
$ ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0 |
|||
# required for autottl mode only |
|||
$ ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0 |
|||
$ /opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 |
|||
``` |
|||
|
|||
|
|||
### PF в FreeBSD |
|||
Настройка аналогична **OpenBSD**, но есть важные нюансы. |
|||
|
|||
1. В **FreeBSD** поддержка PF в `tpws` отключена по умолчанию. Чтобы ее |
|||
включить, нужно использовать параметр `--enable-pf`. |
|||
2. Нельзя сделать **ipv6** rdr на `::1`. Нужно делать на *link-local* адрес |
|||
входящего интерфейса. Смотрите через `ifconfig` адрес `fe80:...` и |
|||
добавляете в правило |
|||
3. Синтаксис `pf.conf` немного отличается. Более новая версия **PF**. |
|||
4. Лимит на количество элементов таблиц задается так: |
|||
```sh |
|||
$ sysctl net.pf.request_maxcount=2000000 |
|||
``` |
|||
5. *divert-to* сломан. Он работает, но не работает механизм предотвращения |
|||
зацикливаний. Кто-то уже написал патч, но в `14-RELEASE` проблема все еще |
|||
есть. Следовательно, на данный момент работа `dvtws` через **PF** |
|||
невозможна. |
|||
|
|||
- `/etc/pf.conf`: |
|||
``` |
|||
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::31c:29ff:dee2:1c4d port 988 |
|||
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 |
|||
``` |
|||
|
|||
```sh |
|||
$ /opt/zapret/tpws/tpws --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force |
|||
``` |
|||
|
|||
> В PF непонятно как делать rdr-to с той же системы, где работает proxy. |
|||
> Вариант с route-to у меня не заработал. |
|||
|
|||
|
|||
### pfsense |
|||
#### Что это |
|||
**pfsense** основан на **FreeBSD** и использует фаервол **PF**, имеющий |
|||
проблемы с *divert*. К счастью, модули **ipfw** и **ipdivert** присутствуют в |
|||
поставке последних версий **pfsense**. Их можно подгрузить через `kldload`. |
|||
|
|||
#### Особенности |
|||
В некоторых более старых версиях **pfsense** требуется изменить порядок |
|||
фаерволов через `sysctl`, сделав **ipfw** первым. В более новых эти параметры |
|||
`sysctl` отсутствуют, но система работает как надо и без них. В некоторых |
|||
случаях фаервол **PF** может ограничивать возможности `dvtws`, в частности в |
|||
области фрагментации ip. |
|||
|
|||
#### Исполняемые файлы |
|||
Присутствуют по умолчанию правила scrub для реассемблинга фрагментов. |
|||
Бинарики из [`binaries/freebsd-x64`](../binaries/freebsd-x64) собраны под |
|||
**FreeBSD 11**. Они должны работать и на последующих версиях **FreeBSD**, |
|||
включая **pfsense**. Можно пользоваться `install_bin.sh`. |
|||
|
|||
#### Автозапуск |
|||
Пример скрипта автозапуска лежит в [`init.d/pfsense`](../init.d/pfsense). Его |
|||
следует поместить в `/usr/local/etc/rc.d` и отредактировать на предмет правил |
|||
**ipfw** и запуска демонов. Есть встроенный редактор `edit` как более |
|||
приемлемая альтернатива `vi`. |
|||
|
|||
> [!NOTE] |
|||
> Поскольку `git` отсутствует, копировать файлы удобнее всего через `ssh`. |
|||
> `curl` присутствует по умолчанию. Можно скопировать zip с файлами zapret и |
|||
> распаковать в `/opt`, как это делается на других системах. Тогда `dvtws` |
|||
> нужно запускать как `/opt/zapret/nfq/dvtws`. Либо скопировать только `dvtws` |
|||
> в `/usr/local/sbin`. Как вам больше нравится. |
|||
|
|||
> [!NOTE] |
|||
> Скрипты ipset работают, крон есть. Можно сделать автообновление листов. |
|||
|
|||
> [!NOTE] |
|||
> Если вас напрягает бедность имеющегося репозитория, можно включить |
|||
> репозиторий от **FreeBSD**, который по умолчанию выключен. |
|||
> |
|||
> Поменяйте *no* на *yes* в `/usr/local/etc/pkg/repos/FreeBSD.conf` |
|||
> |
|||
> Можно установить весь привычный софт, включая `git`, чтобы напрямую скачивать |
|||
> zapret с github. |
|||
|
|||
- `/usr/local/etc/rc.d/zapret.sh` (chmod `755`): |
|||
```sh |
|||
#!/bin/sh |
|||
|
|||
kldload ipfw |
|||
kldload ipdivert |
|||
|
|||
# for older pfsense versions. newer do not have these sysctls |
|||
sysctl net.inet.ip.pfil.outbound=ipfw,pf |
|||
sysctl net.inet.ip.pfil.inbound=ipfw,pf |
|||
sysctl net.inet6.ip6.pfil.outbound=ipfw,pf |
|||
sysctl net.inet6.ip6.pfil.inbound=ipfw,pf |
|||
|
|||
ipfw delete 100 |
|||
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0 |
|||
pkill ^dvtws$ |
|||
dvtws --daemon --port 989 --dpi-desync=split2 |
|||
|
|||
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state |
|||
pfctl -d ; pfctl -e |
|||
``` |
|||
|
|||
#### Проблемы tpws |
|||
Что касается `tpws`, то видимо имеется некоторый конфликт двух фаерволов, и |
|||
правила fwd в **ipfw** не работают. Работает перенаправление средствами **PF** |
|||
как описано в разделе по **FreeBSD**. В **PF** можно изменять правила только |
|||
целыми блоками - якорями (anchors). Нельзя просто так добавить или удалить |
|||
что-то. Но чтобы какой-то anchor был обработан, на него должна быть ссылка из |
|||
основного набора правил. Его трогать нельзя, иначе порушится весь фаервол. |
|||
Поэтому придется править код скриптов pfsense. |
|||
|
|||
1. Поправьте `/etc/inc/filter.inc` следующим образом: |
|||
``` |
|||
<...> |
|||
/* MOD */ |
|||
$natrules .= "# ZAPRET redirection\n"; |
|||
$natrules .= "rdr-anchor \"zapret\"\n"; |
|||
|
|||
$natrules .= "# TFTP proxy\n"; |
|||
$natrules .= "rdr-anchor \"tftp-proxy/*\"\n"; |
|||
<...> |
|||
``` |
|||
|
|||
2. Напишите файл с содержимым anchor-а (например, `/etc/zapret.anchor`): |
|||
``` |
|||
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::20c:29ff:5ae3:4821 port 988 |
|||
``` |
|||
|
|||
`fe80::20c:29ff:5ae3:4821` замените на ваш link local адрес **LAN** интерфейса, |
|||
либо уберите строчку, если **ipv6** не нужен. |
|||
|
|||
3. Добавьте в автозапуск `/usr/local/etc/rc.d/zapret.sh`: |
|||
```sh |
|||
$ pfctl -a zapret -f /etc/zapret.anchor |
|||
$ pkill ^tpws$ |
|||
$ tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2 |
|||
``` |
|||
|
|||
4. После перезагрузки проверьте, что правила создались: |
|||
```sh |
|||
$ pfctl -s nat |
|||
no nat proto carp all |
|||
nat-anchor "natearly/*" all |
|||
nat-anchor "natrules/*" all |
|||
<...> |
|||
no rdr proto carp all |
|||
rdr-anchor "zapret" all |
|||
rdr-anchor "tftp-proxy/*" all |
|||
rdr-anchor "miniupnpd" all |
|||
|
|||
$ pfctl -s nat -a zapret |
|||
rdr pass on em1 inet proto tcp from any to any port = http -> 127.0.0.1 port 988 |
|||
rdr pass on em1 inet proto tcp from any to any port = https -> 127.0.0.1 port 988 |
|||
rdr pass on em1 inet6 proto tcp from any to any port = http -> fe80::20c:29ff:5ae3:4821 port 988 |
|||
rdr pass on em1 inet6 proto tcp from any to any port = https -> fe80::20c:29ff:5ae3:4821 port 988 |
|||
``` |
|||
|
|||
> [!NOTE] |
|||
> Так же есть более элегантный способ запуска `tpws` через @reboot в `cron` и |
|||
> правило перенаправления в UI. Это позволит не редактировать код pfsense. |
|||
|
|||
|
|||
## OpenBSD |
|||
|
|||
### tpws бинд на ipv4 |
|||
В `tpws` бинд по умолчанию только на **ipv6**. для бинда на **ipv4** указать |
|||
`--bind-addr=0.0.0.0` Используйте `--bind-addr=0.0.0.0 --bind-addr=::` для |
|||
достижения того же результата, как в других ОС по умолчанию. Но лучше все же |
|||
так не делать, а сажать на определенные внутренние адреса или интерфейсы. |
|||
|
|||
|
|||
### tpws для проходящего трафика |
|||
|
|||
- `/etc/pf.conf`: |
|||
``` |
|||
pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988 |
|||
pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988 |
|||
``` |
|||
|
|||
```sh |
|||
$ pfctl -f /etc/pf.conf |
|||
$ tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 |
|||
``` |
|||
|
|||
> [!NOTE] |
|||
> В **PF** непонятно как делать rdr-to с той же системы, где работает proxy. |
|||
> Вариант с route-to у меня не заработал. Поддержка rdr-to реализована через |
|||
> `/dev/pf`, поэтому прозрачный режим **требует root**. |
|||
|
|||
|
|||
### Запуск `dvtws` |
|||
|
|||
#### Весь трафик |
|||
- `/etc/pf.conf`: |
|||
``` |
|||
pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 proto tcp from port {80,443} no state |
|||
pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no state |
|||
``` |
|||
|
|||
```sh |
|||
$ pfctl -f /etc/pf.conf |
|||
$ ./dvtws --port=989 --dpi-desync=split2 |
|||
``` |
|||
|
|||
#### Трафик только на таблицу zapret |
|||
> За исключением таблицы nozapret |
|||
|
|||
- `/etc/pf.conf`: |
|||
``` |
|||
set limit table-entries 2000000 |
|||
table <zapret> file "/opt/zapret/ipset/zapret-ip.txt" |
|||
table <zapret-user> file "/opt/zapret/ipset/zapret-ip-user.txt" |
|||
table <nozapret> file "/opt/zapret/ipset/zapret-ip-exclude.txt" |
|||
pass out quick on em0 inet proto tcp to <nozapret> port {80,443} |
|||
pass in quick on em0 inet proto tcp from <zapret> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet proto tcp from <zapret> port {80,443} no state |
|||
pass out quick on em0 inet proto tcp to <zapret> port {80,443} divert-packet port 989 no state |
|||
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} no state |
|||
pass out quick on em0 inet proto tcp to <zapret-user> port {80,443} divert-packet port 989 no state |
|||
table <zapret6> file "/opt/zapret/ipset/zapret-ip6.txt" |
|||
table <zapret6-user> file "/opt/zapret/ipset/zapret-ip-user6.txt" |
|||
table <nozapret6> file "/opt/zapret/ipset/zapret-ip-exclude6.txt" |
|||
pass out quick on em0 inet6 proto tcp to <nozapret6> port {80,443} |
|||
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} no state |
|||
pass out quick on em0 inet6 proto tcp to <zapret6> port {80,443} divert-packet port 989 no state |
|||
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} no state |
|||
pass out quick on em0 inet6 proto tcp to <zapret6-user> port {80,443} divert-packet port 989 no state |
|||
``` |
|||
|
|||
```sh |
|||
$ pfctl -f /etc/pf.conf |
|||
$ ./dvtws --port=989 --dpi-desync=split2 |
|||
``` |
|||
|
|||
|
|||
### Проблемы с badsum |
|||
**OpenBSD** принудительно пересчитывает tcp checksum после divert, поэтому |
|||
скорее всего `dpi-desync-fooling=badsum` у вас не заработает. При использовании |
|||
этого параметра `dvtws` предупредит о возможной проблеме. |
|||
|
|||
|
|||
### Особенность отправки fake пакетов |
|||
В **OpenBSD** `dvtws` все фейки отсылает через divert socket, поскольку эта |
|||
возможность через raw sockets заблокирована. Видимо **PF** автоматически |
|||
предотвращает повторный заворот diverted фреймов, поэтому проблемы зацикливания |
|||
нет. |
|||
|
|||
|
|||
### Возможная оптимизация трафика |
|||
divert-packet автоматически вносит обратное правило для перенаправления. Трюк с |
|||
no state и in правилом позволяет обойти эту проблему, чтобы напрасно не гнать |
|||
массивный трафик через `dvtws`. |
|||
|
|||
|
|||
### Перезагрузка PF таблиц |
|||
Скрипты из **ipset** не перезагружают таблицы в **PF** по умолчанию. |
|||
|
|||
Чтобы они это делали, добавьте параметр в `/opt/zapret/config`: |
|||
``` |
|||
LISTS_RELOAD="pfctl -f /etc/pf.conf" |
|||
``` |
|||
|
|||
Более новые версии `pfctl` понимают команду перезагрузить только таблицы: |
|||
> [!NOTE] |
|||
> Но это не относится к **OpenBSD 6.8**. В новых **FreeBSD** есть. |
|||
```sh |
|||
$ pfctl -Tl -f /etc/pf.conf |
|||
``` |
|||
|
|||
> [!IMPORTANT] |
|||
> Не забудьте выключить сжатие gzip: `GZIP_LISTS=0` |
|||
|
|||
> [!IMPORTANT] |
|||
> Если в вашей конфигурации какого-то файла листа нет, то его необходимо |
|||
> исключить из правил PF. Если вдруг листа нет, и он задан в pf.conf, будет |
|||
> ошибка перезагрузки фаервола. |
|||
|
|||
> [!NOTE] |
|||
> После настройки обновление листов можно поместить в `cron`: |
|||
> ```sh |
|||
> $ crontab -e |
|||
> ``` |
|||
> |
|||
> ``` |
|||
> <...> |
|||
> 0 12 */2 * * /opt/zapret/ipset/get_config.sh |
|||
> ``` |
|||
|
|||
|
|||
## MacOS |
|||
### Введение |
|||
Иначально ядро этой ОС "darwin" основывалось на **BSD**, потому в ней много |
|||
похожего на другие версии **BSD**. Однако, как и в других массовых коммерческих |
|||
проектах, приоритеты смещаются в сторону от оригинала. Яблочники что хотят, то |
|||
и творят. |
|||
|
|||
|
|||
### dvtws бесполезен |
|||
Раньше был **ipfw**, потом его убрали, заменили на **PF**. Есть сомнения, что |
|||
*divert сокеты* в ядре остались. Попытка создать *divert socket* не выдает |
|||
ошибок, но полученный сокет ведет себя точно так же, как *raw*, со всеми его |
|||
унаследованными косяками + еще яблочно специфическими. В **PF** *divert-packet* |
|||
не работает. Простой grep бинарика `pfctl` показывает, что там нет слова |
|||
"divert", а в других версиях **BSD** оно есть. `dvtws` собирается, но |
|||
совершенно бесполезен. |
|||
|
|||
|
|||
### tpws |
|||
`tpws` удалось адаптировать, он работоспособен. Получение адреса назначения для |
|||
прозрачного прокси в **PF** (`DIOCNATLOOK`) убрали из заголовков в новых SDK, |
|||
сделав фактически недокументированным. |
|||
|
|||
В `tpws` перенесены некоторые определения из более старых версий яблочных SDK. |
|||
С ними удалось завести прозрачный режим. Однако, что будет в следующих версиях |
|||
угадать сложно. Гарантий нет. Еще одной особенностью **PF** в **MacOS** |
|||
является проверка на рута в момент обращения к `/dev/pf`, чего нет в остальных |
|||
**BSD**. `tpws` по умолчанию сбрасывает рутовые привилегии. Необходимо явно |
|||
указать параметр `--user=root`. В остальном **PF** себя ведет похоже на |
|||
**FreeBSD**. Синтаксис `pf.conf` тот же. |
|||
|
|||
> [!IMPORTANT] |
|||
> На **MacOS** работает редирект как с проходящего трафика, так и с локальной |
|||
> системы через route-to. Поскольку `tpws` вынужден работать под root, для |
|||
> исключения рекурсии приходится пускать исходящий от root трафик напрямую. |
|||
> Отсюда имеем недостаток - **обход DPI для рута работать НЕ будет**. |
|||
|
|||
#### Работа в прозрачном режиме только для исходящих запросов |
|||
- `/etc/pf.conf`: |
|||
``` |
|||
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988 |
|||
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root } |
|||
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root } |
|||
``` |
|||
|
|||
```sh |
|||
$ pfctl -ef /etc/pf.conf |
|||
$ /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force |
|||
``` |
|||
|
|||
#### Работа в прозрачном режиме |
|||
> [!NOTE] |
|||
> Предполагается, что имя LAN интерфейса - `en1` |
|||
|
|||
```sh |
|||
$ ifconfig en1 | grep fe80 |
|||
inet6 fe80::bbbb:bbbb:bbbb:bbbb%en1 prefixlen 64 scopeid 0x8 |
|||
``` |
|||
|
|||
- `/etc/pf.conf`: |
|||
``` |
|||
rdr pass on en1 inet proto tcp from any to any port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on en1 inet6 proto tcp from any to any port {80,443} -> fe80::bbbb:bbbb:bbbb:bbbb port 988 |
|||
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988 |
|||
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root } |
|||
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root } |
|||
``` |
|||
|
|||
```sh |
|||
$ pfctl -ef /etc/pf.conf |
|||
$ /opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force --bind-iface6=en1 --bind-linklocal=force |
|||
``` |
|||
|
|||
|
|||
### Проблема link-local адреса |
|||
Если вы пользуетесь **MaсOS** в качестве **ipv6** роутера, то нужно будет |
|||
решить вопрос с регулярно изменяемым link-local адресом. С некоторых версий |
|||
**MacOS** использует по умолчанию постоянные "secured" ipv6 адреса вместо |
|||
генерируемых на базе MAC адреса. |
|||
|
|||
Все замечательно, но есть одна проблема. Постоянными остаются только global |
|||
scope адреса. Link locals периодически меняются. Смена завязана на системное |
|||
время. Перезагрузки адрес не меняют, Но если перевести время на день вперед и |
|||
перезагрузиться - link local станет другим (по крайней мере в vmware это так). |
|||
Информации по вопросу крайне мало, но тянет на баг. Не должен меняться link |
|||
local. Скрывать link local не имеет смысла, а динамический link local нельзя |
|||
использовать в качестве адреса шлюза. Проще всего отказаться от "secured" |
|||
адресов. Для этого поместите строчку `net.inet6.send.opmode=0` в |
|||
`/etc/sysctl.conf` и перезагрузите систему. |
|||
|
|||
Все равно для исходящих соединений будут использоваться temporary адреса, как и |
|||
в других системах. Или вам идея не по вкусу, можно прописать дополнительный |
|||
статический **ipv6** из диапазона маски `fc00::/7` - выберите любой с длиной |
|||
префикса `128`. Это можно сделать в системных настройках, создав дополнительный |
|||
адаптер на базе того же сетевого интерфейса, отключить в нем **ipv4** и вписать |
|||
статический **ipv6**. Он добавится к автоматически настраеваемым. |
|||
|
|||
|
|||
### Сборка |
|||
```sh |
|||
$ make -C /opt/zapret mac |
|||
``` |
|||
|
|||
> [!IMPORTANT] |
|||
> Скрипты получения листов ipset/*.sh работают. Если будете пользоваться |
|||
> `ipset/get_combined.sh`, нужно установить `GNU grep` через `brew`. Имеющийся |
|||
> очень старый и безумно медленный с оцией `-f`. |
|||
|
|||
|
|||
### Простая установка |
|||
В **MacOS** поддерживается `install_easy.sh` |
|||
|
|||
В комплекте идут бинарики, собраные под 64-bit с опцией |
|||
`-mmacosx-version-min=10.8`. Они должны работать на всех поддерживаемых версиях |
|||
**MacOS**. Если вдруг не работают - можно собрать свои. Developer tools |
|||
ставятся автоматом при запуске `make`. |
|||
|
|||
> [!WARNING] |
|||
> Internet sharing средствами системы **не поддерживается**! |
|||
> |
|||
> Поддерживается только роутер, настроенный своими силами через **PF**. Если вы |
|||
> вдруг включили шаринг, а потом выключили, то доступ к сайтам может пропасть |
|||
> совсем. |
|||
> |
|||
> Лечение: |
|||
> ```sh |
|||
> $ pfctl -f /etc/pf.conf |
|||
> ``` |
|||
> |
|||
> Если вам нужен шаринг интернета, лучше отказаться от прозрачного режима и |
|||
> использовать socks прокси. |
|||
|
|||
Для автостарта используется **launchd** (`/Library/LaunchDaemons/zapret.plist`) |
|||
Управляющий скрипт : `/opt/zapret/init.d/macos/zapret` |
|||
|
|||
Следующие команды работают с `tpws` и фаерволом одновременно (если |
|||
`INIT_APPLY_FW=1` в config) |
|||
|
|||
```sh |
|||
$ /opt/zapret/init.d/macos/zapret start |
|||
$ /opt/zapret/init.d/macos/zapret stop |
|||
$ /opt/zapret/init.d/macos/zapret restart |
|||
``` |
|||
|
|||
Работа только с tpws: |
|||
```sh |
|||
$ /opt/zapret/init.d/macos/zapret start-daemons |
|||
$ /opt/zapret/init.d/macos/zapret stop-daemons |
|||
$ /opt/zapret/init.d/macos/zapret restart-daemons |
|||
|
|||
Работа только с PF: |
|||
```sh |
|||
$ /opt/zapret/init.d/macos/zapret start-fw |
|||
$ /opt/zapret/init.d/macos/zapret stop-fw |
|||
$ /opt/zapret/init.d/macos/zapret restart-fw |
|||
``` |
|||
|
|||
Перезагрузка всех IP таблиц из файлов: |
|||
```sh |
|||
$ /opt/zapret/init.d/macos/zapret reload-fw-tables |
|||
``` |
|||
|
|||
> [!NOTE] |
|||
> Инсталятор настраивает `LISTS_RELOAD` в config, так что скрипты |
|||
> [`ipset/*.sh`](../ipset/) автоматически перезагружают IP таблицы в PF. |
|||
|
|||
> [!NOTE] |
|||
> Автоматически создается cron job на `ipset/get_config.sh`, по аналогии с |
|||
> openwrt. |
|||
|
|||
При start-fw скрипт автоматически модицифирует `/etc/pf.conf`, вставляя туда |
|||
anchors "zapret". Модификация расчитана на `pf.conf`, в котором сохранены |
|||
дефолтные anchors от apple. Если у вас измененный `pf.conf` и модификация не |
|||
удалась, об этом будет предупреждение. Не игнорируйте его. В этом случае вам |
|||
нужно вставить в свой `pf.conf` (в соответствии с порядком типов правил): |
|||
``` |
|||
rdr-anchor "zapret" |
|||
anchor "zapret" |
|||
``` |
|||
|
|||
> [!NOTE] |
|||
> При деинсталяции через `uninstall_easy.sh` модификации `pf.conf` убираются. |
|||
|
|||
> [!NOTE] |
|||
> start-fw создает 3 файла anchors в `/etc/pf.anchors`: `zapret`, `zapret-v4`, |
|||
> `zapret-v6`. Последние 2 подключаются из anchor "zapret". |
|||
|
|||
> [!NOTE] |
|||
> Таблицы `nozapret` и `nozapret6` принадлежат anchor "zapret". |
|||
> |
|||
> Таблицы `zapret` и `zapret-user` в anchor "zapret-v4". |
|||
> |
|||
> Таблицы `zapret6` и `zapret6-user` в anchor "zapret-v6". |
|||
> |
|||
> Если какая-то версия протокола отключена - соответствующий anchor пустой и не |
|||
> упоминается в anchor "zapret". Таблицы и правила создаются только на те |
|||
> листы, которые фактически есть в директории ipset. |
|||
|
|||
|
|||
### Вариант Custom |
|||
Так же как и в других системах, поддерживаемых в простом инсталяторе, можно |
|||
создавать свои custom скрипты. |
|||
|
|||
Расположение: `/opt/zapret/init.d/macos/custom` |
|||
|
|||
`zapret_custom_daemons()` получает в `$1`: `0` или `1`. `0` = stop, `1` = start |
|||
|
|||
custom firewall отличается от linux варианта. Вместо заполнения `iptables` вам |
|||
нужно сгенерировать правила для `zapret-v4` и `zapret-v6` anchors и выдать их в |
|||
**stdout**. Это делается в функциях `zapret_custom_firewall_v4()` и |
|||
`zapret_custom_firewall_v6()`. Определения таблиц заполняются основным скриптом |
|||
- вам это делать не нужно. Можно ссылаться на таблицы zapret и zapret-user в |
|||
v4, zapret6 и zapret6-user. |
|||
|
|||
Cм. пример [в файле](../init.d/macos/custom.d.examples/50-extra-tpws) |
@ -1,476 +0,0 @@ |
|||
Поддерживаемые версии |
|||
--------------------- |
|||
|
|||
FreeBSD 11.x+ , OpenBSD 6.x+, частично MacOS Sierra+ |
|||
|
|||
На более старых может собираться, может не собираться, может работать или не работать. |
|||
На FreeBSD 10 собирается и работает dvtws. С tpws есть проблемы из-за слишком старой версии компилятора clang. |
|||
Вероятно, будет работать, если обновить компилятор. |
|||
Возможна прикрутка к последним версиям pfsense без веб интерфейса в ручном режиме через консоль. |
|||
|
|||
|
|||
Особенности BSD систем |
|||
---------------------- |
|||
|
|||
В BSD нет nfqueue. Похожий механизм - divert sockets. |
|||
Из каталога "nfq" под BSD собирается dvtws вместо nfqws. |
|||
Он разделяет с nfqws большую часть кода и почти совпадает по параметрам командной строки. |
|||
|
|||
FreeBSD содержит 3 фаервола : IPFilter, ipfw и Packet Filter (PF). OpenBSD содержит только PF. |
|||
|
|||
Под FreeBSD tpws и dvtws собираются через "make", под OpenBSD - "make bsd", под MacOS - "make mac". |
|||
FreeBSD make распознает BSDmakefile , OpenBSD и MacOS - нет. Поэтому там используется отдельный target в Makefile. |
|||
Сборка всех исходников : make -C /opt/zapret |
|||
|
|||
divert сокет - внутренний тип сокета ядра BSD. Он не привязывается ни к какому сетевому адресу, не участвует |
|||
в обмене данными через сеть и идентифицируется по номеру порта 1..65535. Аналогия с номером очереди NFQUEUE. |
|||
На divert сокеты заворачивается трафик посредством правил ipfw или PF. |
|||
Если в фаерволе есть правило divert, но на divert порту никто не слушает, то пакеты дропаются. |
|||
Это поведение аналогично правилам NFQUEUE без параметра --queue-bypass. |
|||
На FreeBSD divert сокеты могут быть только ipv4, хотя на них принимаются и ipv4, и ipv6 фреймы. |
|||
На OpenBSD divert сокеты создаются отдельно для ipv4 и ipv6 и работают только с одной версией ip каждый. |
|||
На MacOS похоже, что divert сокеты из ядра вырезаны. См подробнее раздел про MacOS. |
|||
Отсылка в divert сокет работает аналогично отсылке через raw socket на linux. Передается полностью IP фрейм, начиная |
|||
с ip загловка . Эти особенности учитываются в dvtws. |
|||
|
|||
Скрипты ipset/*.sh при наличии ipfw работают с ipfw lookup tables. |
|||
Это прямой аналог ipset. lookup tables не разделены на v4 и v6. Они могут содержать v4 и v6 адреса и подсети одновременно. |
|||
Если ipfw отсутствует, то действие зависит от переменной LISTS_RELOAD в config. |
|||
Если она задана, то выполняется команда из LISTS_RELOAD. В противном случае не делается ничего. |
|||
Если LISTS_RELOAD=-, то заполнение таблиц отключается даже при наличии ipfw. |
|||
|
|||
PF может загружать ip таблицы из файла. Чтобы использовать эту возможность следует отключить сжатие gzip для листов |
|||
через параметр файла config "GZIP_LISTS=0". |
|||
|
|||
BSD не содержит системного вызова splice. tpws работает через переброску данных в user mode в оба конца. |
|||
Это медленнее, но не критически. |
|||
Управление асинхронными сокетами в tpws основано на linux-specific механизме epoll. |
|||
В BSD для его эмуляции используется epoll-shim - прослойка для эмуляции epoll на базе kqueue. |
|||
|
|||
mdig и ip2net полностью работоспособны в BSD. В них нет ничего системо-зависимого. |
|||
|
|||
FreeBSD |
|||
------- |
|||
|
|||
divert сокеты требуют специального модуля ядра ipdivert. |
|||
Поместите следующие строки в /boot/loader.conf (создать, если отсутствует) : |
|||
----------- |
|||
ipdivert_load="YES" |
|||
net.inet.ip.fw.default_to_accept=1 |
|||
----------- |
|||
В /etc/rc.conf : |
|||
----------- |
|||
firewall_enable="YES" |
|||
firewall_script="/etc/rc.firewall.my" |
|||
----------- |
|||
/etc/rc.firewall.my : |
|||
----------- |
|||
ipfw -q -f flush |
|||
----------- |
|||
В /etc/rc.firewall.my можно дописывать правила ipfw, чтобы они восстанавливались после перезагрузки. |
|||
Оттуда же можно запускать и демоны zapret, добавив в параметры "--daemon". Например так : |
|||
----------- |
|||
pkill ^dvtws$ |
|||
/opt/zapret/nfq/dvtws --port=989 --daemon --dpi-desync=split2 |
|||
----------- |
|||
Для перезапуска фаервола и демонов достаточно будет сделать : /etc/rc.d/ipfw restart |
|||
|
|||
|
|||
Краткая инструкция по запуску tpws в прозрачном режиме. |
|||
Предполагается, что интерфейс LAN называется em1, WAN - em0. |
|||
|
|||
Для всего трафика : |
|||
ipfw delete 100 |
|||
ipfw add 100 fwd 127.0.0.1,988 tcp from me to any 80,443 proto ip4 xmit em0 not uid daemon |
|||
ipfw add 100 fwd ::1,988 tcp from me to any 80,443 proto ip6 xmit em0 not uid daemon |
|||
ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1 |
|||
ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 |
|||
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 |
|||
|
|||
Для трафика только на таблицу zapret, за исключением таблицы nozapret : |
|||
ipfw delete 100 |
|||
ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 |
|||
ipfw add 100 fwd 127.0.0.1,988 tcp from me to table\(zapret\) 80,443 proto ip4 xmit em0 not uid daemon |
|||
ipfw add 100 fwd ::1,988 tcp from me to table\(zapret\) 80,443 proto ip6 xmit em0 not uid daemon |
|||
ipfw add 100 allow tcp from any to table\(nozapret\) 80,443 recv em1 |
|||
ipfw add 100 fwd 127.0.0.1,988 tcp from any to any 80,443 proto ip4 recv em1 |
|||
ipfw add 100 fwd ::1,988 tcp from any to any 80,443 proto ip6 recv em1 |
|||
/opt/zapret/tpws/tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 |
|||
|
|||
Таблицы zapret, nozapret, ipban создаются скриптами из ipset по аналогии с Linux. |
|||
Обновление скриптов можно забить в cron под root : |
|||
crontab -e |
|||
Создать строчку "0 12 */2 * * /opt/zapret/ipset/get_config.sh" |
|||
|
|||
При использовании ipfw tpws не требует повышенных привилегий для реализации прозрачного режима. |
|||
Однако, без рута невозможен бинд на порты <1024 и смена UID/GID. Без смены UID будет рекурсия, |
|||
поэтому правила ipfw нужно создавать с учетом UID, под которым работает tpws. |
|||
Переадресация на порты >=1024 может создать угрозу перехвата трафика непривилегированным |
|||
процессом, если вдруг tpws не запущен. |
|||
|
|||
|
|||
Краткая инструкция по запуску dvtws. |
|||
|
|||
Для всего трафика : |
|||
ipfw delete 100 |
|||
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0 |
|||
# required for autottl mode only |
|||
ipfw add 100 divert 989 tcp from any 80,443 to any tcpflags syn,ack in not diverted recv em0 |
|||
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 |
|||
|
|||
Для трафика только на таблицу zapret, за исключением таблицы nozapret : |
|||
ipfw delete 100 |
|||
ipfw add 100 allow tcp from me to table\(nozapret\) 80,443 |
|||
ipfw add 100 divert 989 tcp from any to table\(zapret\) 80,443 out not diverted not sockarg xmit em0 |
|||
# required for autottl mode only |
|||
ipfw add 100 divert 989 tcp from table\(zapret\) 80,443 to any tcpflags syn,ack in not diverted not sockarg recv em0 |
|||
/opt/zapret/nfq/dvtws --port=989 --dpi-desync=split2 |
|||
|
|||
|
|||
PF в FreeBSD: |
|||
Настройка аналогична OpenBSD, но есть важные нюансы. |
|||
1) В FreeBSD поддержка PF в tpws отключена по умолчанию. Чтобы ее включить, нужно использовать параметр --enable-pf. |
|||
2) Нельзя сделать ipv6 rdr на ::1. Нужно делать на link-local адрес входящего интерфейса. |
|||
Смотрите через ifconfig адрес fe80:... и добавляете в правило |
|||
3) Синтаксис pf.conf немного отличается. Более новая версия PF. |
|||
4) Лимит на количество элементов таблиц задается так : sysctl net.pf.request_maxcount=2000000 |
|||
5) divert-to сломан. Он работает, но не работает механизм предотвращения зацикливаний. |
|||
Кто-то уже написал патч, но в 14-RELEASE проблема все еще есть. |
|||
Следовательно, на данный момент работа dvtws через pf невозможна. |
|||
|
|||
/etc/pf.conf |
|||
----------- |
|||
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::31c:29ff:dee2:1c4d port 988 |
|||
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 |
|||
----------- |
|||
/opt/zapret/tpws/tpws --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force |
|||
|
|||
В PF непонятно как делать rdr-to с той же системы, где работает proxy. Вариант с route-to у меня не заработал. |
|||
|
|||
|
|||
pfsense |
|||
------- |
|||
|
|||
pfsense основано на FreeBSD. |
|||
pfsense использует фаервол pf, а он имеет проблемы с divert. |
|||
К счастью, модули ipfw и ipdivert присутствуют в поставке последних версий pfsense. |
|||
Их можно подгрузить через kldload. |
|||
В некоторых более старых версиях pfsense требуется изменить порядок фаерволов через sysctl, сделав ipfw первым. |
|||
В более новых эти параметры sysctl отсутствуют, но система работает как надо и без них. |
|||
В некоторых случаях фаервол pf может ограничивать возможности dvtws, в частности в области фрагментации ip. |
|||
Присутствуют по умолчанию правила scrub для реассемблинга фрагментов. |
|||
Бинарики из binaries/freebsd-x64 собраны под FreeBSD 11. Они должны работать и на последующих версиях FreeBSD, |
|||
включая pfsense. Можно пользоваться install_bin.sh. |
|||
|
|||
Пример скрипта автозапуска лежит в init.d/pfsense. Его следует поместить в /usr/local/etc/rc.d и отредактировать |
|||
на предмет правил ipfw и запуска демонов. Есть встроенный редактор edit как более приемлемая альтернатива vi. |
|||
Поскольку git отсутствует, копировать файлы удобнее всего через ssh. curl присутствует по умолчанию. |
|||
Можно скопировать zip с файлами zapret и распаковать в /opt, как это делается на других системах. |
|||
Тогда dvtws нужно запускать как /opt/zapret/nfq/dvtws. Либо скопировать только dvtws в /usr/local/sbin. |
|||
Как вам больше нравится. |
|||
ipset скрипты работают, крон есть. Можно сделать автообновление листов. |
|||
|
|||
Если вас напрягает бедность имеющегося репозитория, можно включить репозиторий от FreeBSD, который по умолчанию выключен. |
|||
Поменяйте no на yes в /usr/local/etc/pkg/repos/FreeBSD.conf |
|||
Можно установить весь привычный soft, включая git, чтобы напрямую скачивать zapret с github. |
|||
|
|||
/usr/local/etc/rc.d/zapret.sh (chmod 755) |
|||
----------- |
|||
#!/bin/sh |
|||
|
|||
kldload ipfw |
|||
kldload ipdivert |
|||
|
|||
# for older pfsense versions. newer do not have these sysctls |
|||
sysctl net.inet.ip.pfil.outbound=ipfw,pf |
|||
sysctl net.inet.ip.pfil.inbound=ipfw,pf |
|||
sysctl net.inet6.ip6.pfil.outbound=ipfw,pf |
|||
sysctl net.inet6.ip6.pfil.inbound=ipfw,pf |
|||
|
|||
ipfw delete 100 |
|||
ipfw add 100 divert 989 tcp from any to any 80,443 out not diverted xmit em0 |
|||
pkill ^dvtws$ |
|||
dvtws --daemon --port 989 --dpi-desync=split2 |
|||
|
|||
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state |
|||
pfctl -d ; pfctl -e |
|||
----------- |
|||
|
|||
Что касается tpws, то видимо имеется некоторый конфликт двух фаерволов, и правила fwd в ipfw не работают. |
|||
Работает перенаправление средствами pf как описано в разделе по FreeBSD. |
|||
В pf можно изменять правила только целыми блоками - якорями (anchors). Нельзя просто так добавить или удалить что-то. |
|||
Но чтобы какой-то anchor был обработан, на него должна быть ссылка из основного набора правил. |
|||
Его трогать нельзя, иначе порушится весь фаервол. |
|||
Поэтому придется править код скриптов pfsense. Поправьте /etc/inc/filter.inc следующим образом : |
|||
----------- |
|||
................. |
|||
/* MOD */ |
|||
$natrules .= "# ZAPRET redirection\n"; |
|||
$natrules .= "rdr-anchor \"zapret\"\n"; |
|||
|
|||
$natrules .= "# TFTP proxy\n"; |
|||
$natrules .= "rdr-anchor \"tftp-proxy/*\"\n"; |
|||
................. |
|||
----------- |
|||
|
|||
Напишите файл с содержимым anchor-а (например, /etc/zapret.anchor): |
|||
----------- |
|||
rdr pass on em1 inet proto tcp to port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on em1 inet6 proto tcp to port {80,443} -> fe80::20c:29ff:5ae3:4821 port 988 |
|||
----------- |
|||
fe80::20c:29ff:5ae3:4821 замените на ваш link local адрес LAN интерфейса, либо уберите строчку, если ipv6 не нужен. |
|||
|
|||
Добавьте в автозапуск /usr/local/etc/rc.d/zapret.sh : |
|||
----------- |
|||
pfctl -a zapret -f /etc/zapret.anchor |
|||
pkill ^tpws$ |
|||
tpws --daemon --port=988 --enable-pf --bind-addr=127.0.0.1 --bind-iface6=em1 --bind-linklocal=force --split-http-req=method --split-pos=2 |
|||
----------- |
|||
|
|||
После перезагрузки проверьте, что правила создались : |
|||
----------- |
|||
[root@pfSense /]# pfctl -s nat |
|||
no nat proto carp all |
|||
nat-anchor "natearly/*" all |
|||
nat-anchor "natrules/*" all |
|||
................... |
|||
no rdr proto carp all |
|||
rdr-anchor "zapret" all |
|||
rdr-anchor "tftp-proxy/*" all |
|||
rdr-anchor "miniupnpd" all |
|||
[root@pfSense /]# pfctl -s nat -a zapret |
|||
rdr pass on em1 inet proto tcp from any to any port = http -> 127.0.0.1 port 988 |
|||
rdr pass on em1 inet proto tcp from any to any port = https -> 127.0.0.1 port 988 |
|||
rdr pass on em1 inet6 proto tcp from any to any port = http -> fe80::20c:29ff:5ae3:4821 port 988 |
|||
rdr pass on em1 inet6 proto tcp from any to any port = https -> fe80::20c:29ff:5ae3:4821 port 988 |
|||
----------- |
|||
|
|||
Так же есть более элегантный способ запуска tpws через @reboot в cron и правило перенаправления в UI. |
|||
Это позволит не редактировать код pfsense. |
|||
|
|||
|
|||
OpenBSD |
|||
------- |
|||
|
|||
В tpws бинд по умолчанию только на ipv6. для бинда на ipv4 указать "--bind-addr=0.0.0.0" |
|||
Используйте --bind-addr=0.0.0.0 --bind-addr=:: для достижения того же результата, как в других ОС по умолчанию. |
|||
(лучше все же так не делать, а сажать на определенные внутренние адреса или интерфейсы) |
|||
|
|||
tpws для проходящего трафика : |
|||
|
|||
/etc/pf.conf |
|||
------------ |
|||
pass in quick on em1 inet proto tcp to port {80,443} rdr-to 127.0.0.1 port 988 |
|||
pass in quick on em1 inet6 proto tcp to port {80,443} rdr-to ::1 port 988 |
|||
------------ |
|||
pfctl -f /etc/pf.conf |
|||
tpws --port=988 --user=daemon --bind-addr=::1 --bind-addr=127.0.0.1 |
|||
|
|||
В PF непонятно как делать rdr-to с той же системы, где работает proxy. Вариант с route-to у меня не заработал. |
|||
Поддержка rdr-to реализована через /dev/pf, поэтому прозрачный режим требует root. |
|||
|
|||
dvtws для всего трафика : |
|||
|
|||
/etc/pf.conf |
|||
------------ |
|||
pass in quick on em0 proto tcp from port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 proto tcp from port {80,443} no state |
|||
pass out quick on em0 proto tcp to port {80,443} divert-packet port 989 no state |
|||
------------ |
|||
pfctl -f /etc/pf.conf |
|||
./dvtws --port=989 --dpi-desync=split2 |
|||
|
|||
dvtws для трафика только на таблицу zapret, за исключением таблицы nozapret : |
|||
|
|||
/etc/pf.conf |
|||
------------ |
|||
set limit table-entries 2000000 |
|||
table <zapret> file "/opt/zapret/ipset/zapret-ip.txt" |
|||
table <zapret-user> file "/opt/zapret/ipset/zapret-ip-user.txt" |
|||
table <nozapret> file "/opt/zapret/ipset/zapret-ip-exclude.txt" |
|||
pass out quick on em0 inet proto tcp to <nozapret> port {80,443} |
|||
pass in quick on em0 inet proto tcp from <zapret> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet proto tcp from <zapret> port {80,443} no state |
|||
pass out quick on em0 inet proto tcp to <zapret> port {80,443} divert-packet port 989 no state |
|||
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet proto tcp from <zapret-user> port {80,443} no state |
|||
pass out quick on em0 inet proto tcp to <zapret-user> port {80,443} divert-packet port 989 no state |
|||
table <zapret6> file "/opt/zapret/ipset/zapret-ip6.txt" |
|||
table <zapret6-user> file "/opt/zapret/ipset/zapret-ip-user6.txt" |
|||
table <nozapret6> file "/opt/zapret/ipset/zapret-ip-exclude6.txt" |
|||
pass out quick on em0 inet6 proto tcp to <nozapret6> port {80,443} |
|||
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet6 proto tcp from <zapret6> port {80,443} no state |
|||
pass out quick on em0 inet6 proto tcp to <zapret6> port {80,443} divert-packet port 989 no state |
|||
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} flags SA/SA divert-packet port 989 no state |
|||
pass in quick on em0 inet6 proto tcp from <zapret6-user> port {80,443} no state |
|||
pass out quick on em0 inet6 proto tcp to <zapret6-user> port {80,443} divert-packet port 989 no state |
|||
------------ |
|||
pfctl -f /etc/pf.conf |
|||
./dvtws --port=989 --dpi-desync=split2 |
|||
|
|||
divert-packet автоматически вносит обратное правило для перенаправления. |
|||
Трюк с no state и in правилом позволяет обойти эту проблему, чтобы напрасно не гнать массивный трафик через dvtws. |
|||
|
|||
В OpenBSD dvtws все фейки отсылает через divert socket, поскольку эта возможность через raw sockets заблокирована. |
|||
Видимо pf автоматически предотвращает повторный заворот diverted фреймов, поэтому проблемы зацикливания нет. |
|||
|
|||
OpenBSD принудительно пересчитывает tcp checksum после divert, поэтому скорее всего |
|||
dpi-desync-fooling=badsum у вас не заработает. При использовании этого параметра |
|||
dvtws предупредит о возможной проблеме. |
|||
|
|||
Скрипты из ipset не перезагружают таблицы в PF по умолчанию. |
|||
Чтобы они это делали, добавьте параметр в /opt/zapret/config : |
|||
LISTS_RELOAD="pfctl -f /etc/pf.conf" |
|||
Более новые версии pfctl понимают команду перезагрузить только таблицы : pfctl -Tl -f /etc/pf.conf |
|||
Но это не относится к OpenBSD 6.8. В новых FreeBSD есть. |
|||
Не забудьте выключить сжатие gzip : |
|||
GZIP_LISTS=0 |
|||
Если в вашей конфигурации какого-то файла листа нет, то его необходимо исключить из правил PF. |
|||
Если вдруг листа нет, и он задан в pf.conf, будет ошибка перезагрузки фаервола. |
|||
После настройки обновление листов можно поместить в cron : |
|||
crontab -e |
|||
дописать строчку : 0 12 */2 * * /opt/zapret/ipset/get_config.sh |
|||
|
|||
|
|||
MacOS |
|||
----- |
|||
|
|||
Иначально ядро этой ОС "darwin" основывалось на BSD, потому в ней много похожего на другие версии BSD. |
|||
Однако, как и в других массовых коммерческих проектах, приоритеты смещаются в сторону от оригинала. |
|||
Яблочники что хотят, то и творят. |
|||
Раньше был ipfw, потом его убрали, заменили на PF. |
|||
Есть сомнения, что divert сокеты в ядре остались. Попытка создать divert socket не выдает ошибок, |
|||
но полученный сокет ведет себя точно так же, как raw, со всеми его унаследованными косяками + еще яблочно специфическими. |
|||
В PF divert-packet не работает. Простой grep бинарика pfctl показывает, что там нет слова "divert", |
|||
а в других версиях BSD оно есть. dvtws собирается, но совершенно бесполезен. |
|||
|
|||
tpws удалось адаптировать, он работоспособен. Получение адреса назначения для прозрачного прокси в PF (DIOCNATLOOK) |
|||
убрали из заголовков в новых SDK, сделав фактически недокументированным. |
|||
В tpws перенесены некоторые определения из более старых версий яблочных SDK. С ними удалось завести прозрачный режим. |
|||
Однако, что будет в следующих версиях угадать сложно. Гарантий нет. |
|||
Еще одной особенностью PF в MacOS является проверка на рута в момент обращения к /dev/pf, чего нет в остальных BSD. |
|||
tpws по умолчанию сбрасывает рутовые привилегии. Необходимо явно указать параметр --user=root. |
|||
В остальном PF себя ведет похоже на FreeBSD. Синтаксис pf.conf тот же. |
|||
|
|||
На MacOS работает редирект как с проходящего трафика, так и с локальной системы через route-to. |
|||
Поскольку tpws вынужден работать под root, для исключения рекурсии приходится пускать исходящий от root трафик напрямую. |
|||
Отсюда имеем недостаток : обход DPI для рута работать не будет. |
|||
|
|||
Если вы пользуетесь MaсOS в качестве ipv6 роутера, то нужно будет решить вопрос с регулярно изменяемым link-local адресом. |
|||
С некоторых версий MacOS использует по умолчанию постоянные "secured" ipv6 адреса вместо генерируемых на базе MAC адреса. |
|||
Все замечательно, но есть одна проблема. Постоянными остаются только global scope адреса. |
|||
Link locals периодически меняются. Смена завязана на системное время. Перезагрузки адрес не меняют, |
|||
Но если перевести время на день вперед и перезагрузиться - link local станет другим. (по крайней мере в vmware это так) |
|||
Информации по вопросу крайне мало, но тянет на баг. Не должен меняться link local. Скрывать link local не имеет смысла, |
|||
а динамический link local нельзя использовать в качестве адреса шлюза. |
|||
Проще всего отказаться от "secured" адресов. |
|||
Поместите строчку "net.inet6.send.opmode=0" в /etc/sysctl.conf. Затем перезагрузите систему. |
|||
Все равно для исходящих соединений будут использоваться temporary адреса, как и в других системах. |
|||
Или вам идея не по вкусу, можно прописать дополнительный статический ipv6 из диапазона fc00::/7 - |
|||
выберите любой с длиной префикса 128. Это можно сделать в системных настройках, создав дополнительный адаптер на базе |
|||
того же сетевого интерфейса, отключить в нем ipv4 и вписать статический ipv6. Он добавится к автоматически настраеваемым. |
|||
|
|||
Настройка tpws на macos в прозрачном режиме только для исходящих запросов : |
|||
|
|||
/etc/pf.conf |
|||
------------ |
|||
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988 |
|||
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root } |
|||
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root } |
|||
------------ |
|||
pfctl -ef /etc/pf.conf |
|||
/opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force |
|||
|
|||
|
|||
Настройка tpws на macos роутере в прозрачном режиме, где en1 - LAN. |
|||
|
|||
ifconfig en1 | grep fe80 |
|||
inet6 fe80::bbbb:bbbb:bbbb:bbbb%en1 prefixlen 64 scopeid 0x8 |
|||
/etc/pf.conf |
|||
------------ |
|||
rdr pass on en1 inet proto tcp from any to any port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on en1 inet6 proto tcp from any to any port {80,443} -> fe80::bbbb:bbbb:bbbb:bbbb port 988 |
|||
rdr pass on lo0 inet proto tcp from !127.0.0.0/8 to any port {80,443} -> 127.0.0.1 port 988 |
|||
rdr pass on lo0 inet6 proto tcp from !::1 to any port {80,443} -> fe80::1 port 988 |
|||
pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any port {80,443} user { >root } |
|||
pass out route-to (lo0 fe80::1) inet6 proto tcp from any to any port {80,443} user { >root } |
|||
------------ |
|||
pfctl -ef /etc/pf.conf |
|||
/opt/zapret/tpws/tpws --user=root --port=988 --bind-addr=127.0.0.1 --bind-iface6=lo0 --bind-linklocal=force --bind-iface6=en1 --bind-linklocal=force |
|||
|
|||
|
|||
Сборка : make -C /opt/zapret mac |
|||
|
|||
Скрипты получения листов ipset/*.sh работают. |
|||
Если будете пользоваться ipset/get_combined.sh, нужно установить gnu grep через brew. |
|||
Имеющийся очень старый и безумно медленный с оцией -f. |
|||
|
|||
|
|||
MacOS простая установка |
|||
----------------------- |
|||
|
|||
В MacOS поддерживается install_easy.sh |
|||
|
|||
В комплекте идут бинарики, собраные под 64-bit с опцией -mmacosx-version-min=10.8. |
|||
Они должны работать на всех поддерживаемых версиях macos. |
|||
Если вдруг не работают - можно собрать свои. Developer tools ставятся автоматом при запуске make. |
|||
|
|||
!! Internet sharing средствами системы НЕ ПОДДЕРЖИВАЕТСЯ !! |
|||
Поддерживается только роутер, настроенный своими силами через PF. |
|||
Если вы вдруг включили шаринг, а потом выключили, то доступ к сайтам может пропасть совсем. |
|||
Лечение : pfctl -f /etc/pf.conf |
|||
Если вам нужен шаринг интернета, лучше отказаться от прозрачного режима и использовать socks. |
|||
|
|||
Для автостарта используется launchd (/Library/LaunchDaemons/zapret.plist) |
|||
Управляющий скрипт : /opt/zapret/init.d/macos/zapret |
|||
Следующие команды работают с tpws и фаерволом одновременно (если INIT_APPLY_FW=1 в config) |
|||
/opt/zapret/init.d/macos/zapret start |
|||
/opt/zapret/init.d/macos/zapret stop |
|||
/opt/zapret/init.d/macos/zapret restart |
|||
Работа только с tpws : |
|||
/opt/zapret/init.d/macos/zapret start-daemons |
|||
/opt/zapret/init.d/macos/zapret stop-daemons |
|||
/opt/zapret/init.d/macos/zapret restart-daemons |
|||
Работа только с PF : |
|||
/opt/zapret/init.d/macos/zapret start-fw |
|||
/opt/zapret/init.d/macos/zapret stop-fw |
|||
/opt/zapret/init.d/macos/zapret restart-fw |
|||
Перезагрузка всех IP таблиц из файлов : |
|||
/opt/zapret/init.d/macos/zapret reload-fw-tables |
|||
|
|||
Инсталятор настраивает LISTS_RELOAD в config, так что скрипты ipset/*.sh автоматически перезагружают IP таблицы в PF. |
|||
Автоматически создается cron job на ipset/get_config.sh, по аналогии с openwrt. |
|||
|
|||
При start-fw скрипт автоматически модицифирует /etc/pf.conf, вставляя туда anchors "zapret". |
|||
Модификация расчитана на pf.conf, в котором сохранены дефолтные anchors от apple. |
|||
Если у вас измененный pf.conf и модификация не удалась, об этом будет предупреждение. Не игнорируйте его. |
|||
В этом случае вам нужно вставить в свой pf.conf (в соответствии с порядком типов правил) : |
|||
rdr-anchor "zapret" |
|||
anchor "zapret" |
|||
При деинсталяции через uninstall_easy.sh модификации pf.conf убираются. |
|||
|
|||
start-fw создает 3 файла anchors в /etc/pf.anchors : zapret,zapret-v4,zapret-v6. |
|||
Последние 2 подключаются из anchor "zapret". |
|||
Таблицы nozapret,nozapret6 принадлежат anchor "zapret". |
|||
Таблицы zapret,zapret-user - в anchor "zapret-v4". |
|||
Таблицы zapret6,zapret6-user - в anchor "zapret-v6". |
|||
Если какая-то версия протокола отключена - соответствующий anchor пустой и не упоминается в anchor "zapret". |
|||
Таблицы и правила создаются только на те листы, которые фактически есть в директории ipset. |
|||
|
|||
|
|||
MacOS вариант custom |
|||
-------------------- |
|||
|
|||
Так же как и в других системах, поддерживаемых в простом инсталяторе, можно создавать свои custom скрипты. |
|||
Расположение : /opt/zapret/init.d/macos/custom |
|||
|
|||
zapret_custom_daemons() получает в $1 "0" или "1". "0" - stop, "1" - start |
|||
custom firewall отличается от linux варианта. |
|||
Вместо заполнения iptables вам нужно сгенерировать правила для zapret-v4 и zapret-v6 anchors и выдать их в stdout. |
|||
Это делается в функциях zapret_custom_firewall_v4() и zapret_custom_firewall_v6(). |
|||
Определения таблиц заполняются основным скриптом - вам это делать не нужно. |
|||
Можно ссылаться на таблицы zapret и zapret-user в v4, zapret6 и zapret6-user. |
|||
|
|||
Cм. пример в файле custom-tpws |
Loading…
Reference in new issue