Собственные мобильные прокси при помощи USB модема на FreeBSD

Возникла необходимость в некотором количестве собственных прокси. Да есть кучу готовых сервисов за недорого, но мне они не подходили по тем или иным причинам. Плюс спортивный интерес.
Почитав предварительно Сеть, к удивлению обнаружил, что что то похожее народ поднимает либо на Windows, либо на Linux. И ничего для моей любимой FreeBSD.
На старте у меня было 2 usb-модема, «отвязанные» от операторов. Один со Stick прошивкой, сторой с прошивкой HiLink
Сразу затеялся с модемом с Stick прошивкой, но в итоге перешел на модем с прошивкой HiLink. Скажу что поднимается и на той и на той прошивке. Есть свои плюсы и минусы в каждой.
Stick — с этой прошивкой модем работает как модем и в итоге вы получаете реальный IP на интерфейс
HiLink — с этой прошивкой модем работает как роутер. Т.е на интерфейсе у вас всегда серый IP, а реальный IP на исходящем интерфейсе модема.
На самом деле все не совсем так, но в разрезе данной статьи приймем данное допущение.
FreeBSD 12.1
Модем Huawei e8372h c HiLink прошивкой.

Сначала пытаемся найти модем. После того как мы вставили модем в usb порт чуда не произошло.
Видим в /var/log/messages

ugen3.2: at usbus3
umass0 on uhub0
umass0: on usbus3
umass0: SCSI over Bulk-Only; quirks = 0x0100
umass0:7:0: Attached to scbus7
cd0 at umass-sim0 bus 0 scbus7 target 0 lun 0
cd0: Removable CD-ROM SCSI-2 device
cd0: 40.000MB/s transfers
cd0: 128MB (65536 2048 byte sectors)
cd0: quirks=0x10<10_BYTE_ONLY>

ОК, железка нашлась, но в интерфейсах не появилась.
Устанавливаем следующий софт для работы с модемом

pkg install -y usbutils usb_modeswitch
Cмотрим, как у нас определился модем при включениии в USB:
lsusb
Bus /dev/usb Device /dev/ugen3.2: ID 12d1:1f01 Huawei Technologies Co., Ltd. E353/E3131 (Mass storage mode)

Ищем target-конфиг для модема, чтобы переключить его в сетевую карту.

Ищем модем E3131:

grep -R "E3131" /usr/local/share/usb_modeswitch/
/usr/local/share/usb_modeswitch/12d1:15ce:# Huawei E3531s-2, E3131 (Variant)
/usr/local/share/usb_modeswitch/12d1:151a:# Huawei E392u-12, E3131 (Variant)
/usr/local/share/usb_modeswitch/12d1:15ca:# Huawei E3131
/usr/local/share/usb_modeswitch/12d1:15d0:# Huawei E3131 (Variant)

Я использовал в качестве целевого переключения файл /usr/local/share/usb_modeswitch/12d1:15ca
Даем команду переключения модема, в качестве параметров даем входные параметры из lsusb, а target содержится в файле usb_modeswitch/12d1:15ca

 /usr/local/sbin/usb_modeswitch -v 0x12d1 -p 0x1f01 --config-file /usr/local/share/usb_modeswitch/12d1:15ca
(команда в одну строчку, если вдруг у вас в браузере отобразиться в две)

Если все случилось нормально, даем команду ifconfig и видим новое устройство


#ifconfig


ue0: flags=8843<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether 0c:5b:8f:27:9a:64
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

Модем теперь работает как обычная сетевая карта. Дальше мы работаем с ней как с обычной сетевой.
для полной уверенности получим на нее от модема IP адрес посредством DHCP
dhclient ue0

ue0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
ether 0c:5b:8f:27:9a:64
inet 192.168.8.100 netmask 0xffffff00 broadcast 192.168.8.255
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

Отлично! IP получили. В дальнейшем мы будем назначать его явно при загрузки системы.

Дальше небольшое лирическое отступление.
Поначалу я предполагал что у меня будет сервер с одной сетевой картой с реальным IP и usb-модем.
Пакеты будут приходить с одного интерфейса, а уходить во второй. Увы, так я не смог настроить работу. Возможно я что то не знаю или не умею. Не претендую на истину в последней инстанции. Если у вас получится по другому, готов выложить ваше решение.

После нескольких дней безуспешных попыток решить задачу с двумя сетевыми, я пришел к выводу что мне придется купить и вставить в комп еще одну физическую сетевую карту. (Вполне возможно, что, достаточно было создать vlan, но отлаживать мне было проще на физическом интерфейсе). Итак, под рукой у меня была внешняя usb-карта. Я воткнул ее в свободный usb-порт. Она определилась как обычная сетевая без танцев с бубнами. Зачем все это нужно будет понятно ниже.

Дальше пришлось включить поддержку нескольких таблиц маршрутизации

Добавляем в ядро следующую строку

#Для работы с несолькими таблицами маршрутизации (setfib)
options ROUTETABLES=2 # max 16. 1 is back compatible.

И пересобираем ядро.

Ну и последняя програмка это 3proxy
pkg install 3proxy

Теперь попробуем собрать это в кучу.

В /etc/rc.conf  добавляем следующие строчки:

ifconfig_ue0="inet 192.168.8.100/24"
ifconfig_ue1="inet 10.10.10.1 netmask 255.255.255.0"

ue0 — это интерфейс модема
192.168.8.100 — этот IP выдал мне модем по DHCP, но можно использовать любой из этой подсети кроме первого
ue1 — это вторая сетевая, которая просто вставлена и никуда не подключена.
10.10.10.1 — подсеть которая нам понадобиться в дальнейшем.

Мы помним что у нас теперь есть две независимые таблицы маршрутов. Нумеруются они 0 и 1
Если вы ничего не будете добавлять в таблицу маршрутов 1, то все живет в таблице 0

Поскольку нам нужно будет выходить из сервера не по маршруту по умолчанию заполним таблицу маршрутов 1
В /etc/rc.local добавляем следующие строчки:


ipfw add 130 setfib 1 ip from 192.168.8.0/24 to any
ipfw add 132 setfib 1 ip from 10.10.10.0/24 to any
/usr/sbin/setfib 1 route add default 192.168.8.1

Таким образом весь трафик из подсетей 192.168.8.0/24 и 10.10.10.0/24
будет подчиняться таблице маршрутизации номер 1.
Для этих подсетей маршрутом по умолчанию станет IP 192.168.8.1 — это удаленный адрес нашего модема.

Смотрим что маршруты построились

# setfib 1 netstat -rn
Routing tables (fib: 1)
Internet:
Destination Gateway Flags Netif Expire
default 192.168.8.1 UGS ue0
10.10.10.0/24 link#4 U ue1
127.0.0.1 link#2 UH lo0
178.хх.хх.0/24 link#1 U re0
192.168.8.0/24 link#3 U ue0

можете попробовать пинговать через разные маршруты

setfib 0 ping galayda.com
64 bytes from 178.219.200.9: icmp_seq=0 ttl=58 time=29.381 ms
64 bytes from 178.219.200.9: icmp_seq=1 ttl=58 time=29.604 ms

Это пинг через маршрут по умолчанию
setfib 1 ping galayda.com
64 bytes from 178.219.200.9: icmp_seq=0 ttl=64 time=304.145 ms
64 bytes from 178.219.200.9: icmp_seq=1 ttl=64 time=260.241 ms

Это маршрут через usb модем

Наглядно видно что пакеты в мир ходят через разные итерфейсы.

Теперь настраиваем прокси
По настройке прокси особых «извращений» нет.
Настраивается по куче мануалов имеющихся в сети.
Хотя и тут не без граблей. После всех настроек я так и не смог настроить авторизацию ни по логину ни по IP.
Он тупо пускал всех, невзирая на строчки в конфиге.
Промучавшись еще некоторое время, я принял решение что реализую доступ к прокси посредством правил ipfw

Итак, кроме минимальных правил для запуска 3proxy в /usr/local/etc/3proxy.cfg
была добавлена строчка

socks -i10.10.10.1 -e192.168.8.100 -p1080

socks — я использую именно socks, можно использовать proxy
-i10.10.10.1 это входящий ip на который будут приходить пакеты
-p1080 — это входящий порт
-e192.168.8.100 это ip куда мы перенаправляем трафик с входящего ip

Возвращаемся к файлу /etc/rc.local
#Проброс входящего трафика с внешнего интнрфейса внутрь
ipfw add 140 fwd 10.10.10.1,1080 tcp from any to 178.xx.xx.xx 5555 keep-state
Этим правилом мы заворачиваем все пакеты пришедшие на ip адрес 178.xx.xx.xx и порт 5555 во внутрь сети на
ip адрес 10.10.10.1 и порт 1080
где он будет развернут прокси и выпущен наружу уже через мобильный модем

После этого устанавливаете в своем браузере доступ через прокси 178.xx.xx.xx порт 5555 протокол socks5 и все должно поехать.
Осталось прикрыть ваш прокси сервер снаружи пропуская запросы только с ваших IP адресов

в /usr/local/etc/rc.d создаем файл proxy.sh и делаем его исполняемым
chmod 700 proxy.sh
В этот файл будем вносить ip адреса для которых будет разрешено пользоваться нашим прокси сервером

#!/bin/sh
ipfw table 3 flush
/sbin/ipfw table 3 add 178.хх.хх.хх
/sbin/ipfw table 3 add 185.хх.хх.хх

И /usr/local/etc/rc.d
Дописываем еше две строчки

#Доступ к прокси серверу из вне
ipfw add 128 skipto 140 ip from 'table(3)' to any 5555 in via re0
ipfw add 129 deny log tcp from any to any 5555 in via re0

Командой
ipfw table 3 list
Можно посмотреть каким IP разрешен доступ к вашему прокси

Данная инструкция полностью рабочая и написана в первую очередь для себя, дабы через пол года тупо не смотреть в собственные настройки.
Что еще хочется реализовать:
Подключить второй модем — тут в принципе никаких сложностей, просто по образу и подобию первого
Подключить модем с прошивкой Stick — тут тоже не сложно, но нужно постоянно учитывать что после смены ip нужно динамически менять все правила и в 3proxy и в ipfw
Реализовать web-кнопку нажатие на которую приведет к перезагрузке модема (смена IP по требованию)