Система изоляции устройств для приватности, направленная на предотвращение несанкционированного lateral movement в сети.
Полнофункциональный сканер уязвимостей (vulnerability scanner). Сканирование сетей, серверов, приложений. База данных CVE, NVT, OVAL. Генерация отчётов …
Превращает операционную систему в реляционную базу данных: любой аспект состояния машины (процессы, сетевые соединения, установленные пакеты, …
Платформа для безопасности в реальном времени (XDR + SIEM). Мониторинг файловых изменений, обнаружение вторжений, аудит конфигураций, …
Инструмент для аудита безопасности систем (security auditing). Проверка конфигураций, правил файрвола, SSH, SSL, базы данных, веб-серверов. …
Полная пошаговая инструкция по сборке устройства на Raspberry Pi 4B (8 ГБ): установка Raspberry Pi OS (headless), усиление SSH, отключение IPv6, случайные MAC-адрес и hostname, настройка USB-C Ethernet и точки доступа, подготовка dnsmasq. Полное руководство (20+ разделов) — в README проекта, начиная с раздела «Предварительные требования».
Портативное USB Ethernet-устройство на Raspberry Pi для защиты вашей конфиденциальности
Знаете ли вы о растущей озабоченности европейских правоохранительных органов по поводу того, что люди уходят в тень? Так называемая Высокоуровневая группа (HLG) активно работает над подрывом сквозного шифрования, добиваясь доступа через задние двери к зашифрованным мессенджерам, облачным хранилищам и почтовым сервисам. EDRi разобрала критические изъяны в этом подходе: https://edri.org/?s=going+dark
Если вы ещё не ушли в тень, сейчас самое время!
Этот репозиторий — одновременно руководство и пошаговый учебник по настройке Raspberry Pi 4 в качестве USB Ethernet-устройства. Оно заставляет ваш компьютер направлять весь интернет-трафик через WireGuard VPN или прозрачный прокси Tor, фильтруя исходящий трафик, блокируя рекламу и трекеры, а также подменяя идентификатор устройства для повышения приватности.
Впервые идея этого Ethernet-устройства на Raspberry Pi пришла к нам пять лет назад, когда Apple публично выпустила macOS Big Sur осенью 2020 года. Во время перехода мы заметили, что наша установка Little Snitch — хост-ориентированного межсетевого экрана — частично перестала работать. Конкретно: все процессы Apple больше не фильтровались. Странно.
Изучая проблему в интернете, мы наткнулись на статью исследователя в области безопасности Джеффри Пола под названием Ваш компьютер — не ваш. Его выводы пролили свет на суть проблемы, и мы настоятельно рекомендуем прочитать эту статью перед настройкой собственного устройства для приватности на Raspberry Pi.
Кратко: в современных версиях macOS есть встроенная возможность обходить внутренние межсетевые экраны и VPN. Кроме того, каждый компьютер Apple постоянно подключается к серверам Apple и сторонним сервисам (например, Fastly), чтобы передавать хеши запускаемых приложений — каждый раз, когда вы их открываете:
Это должно быть функцией безопасности для обнаружения вредоносного ПО. Она нужна, чтобы предотвратить запуск вредоносных или заблокированных приложений, если проверка онлайн-сертификата не проходит. Возможно, это и так, но это также означает, что Apple всегда может определить, когда вы в сети, где находитесь, как долго используете определённое ПО (например, VMWare Fusion) или когда запускаете Tor Browser вместо Safari.
Со временем этот сбор данных формирует крайне детализированный профиль ваших цифровых привычек, физических перемещений и паттернов активности. Хуже того, эту информацию можно потенциально сопоставить с другими большими данными от корпораций вроде Google, Microsoft и Facebook. Как метко замечает Джеффри Пол:
С октября 2012 года Apple является партнёром программы слежки PRISM сообщества военной разведки США, которая предоставляет федеральной полиции и армии США неограниченный доступ к этим данным без ордера, всякий раз, когда они его запрашивают. Мы рассматриваем это как крайне тревожное развитие событий: ещё один шаг в сторону надзорного капитализма, подрывающий конфиденциальность всех пользователей Apple.
Справедливости ради, Apple столкнулась с серьёзной критикой за эти практики. В результате некоторые из этих вторжений, такие как ContentFilterExclusionList, который позволял родным приложениям Apple обходить локальные брандмауэры и VPN, были отменены: Стена без дыры.
Согласно Apple, конфиденциальность — это фундаментальное право человека:
Конфиденциальность — это фундаментальное право человека. В Apple это также одна из наших основных ценностей. Ваши устройства важны для многих аспектов вашей жизни. То, чем вы делитесь из этих опытов, и с кем вы этим делитесь, должно зависеть только от вас. Мы разрабатываем продукты Apple так, чтобы защищать вашу конфиденциальность и давать вам контроль над вашей информацией. Это не всегда легко. Но это тот вид инноваций, в которые мы верим.
Однако заявлять о глубокой заботе о конфиденциальности пользователей, одновременно официально поддерживая Закон CLOUD и участвуя в программах вроде PRISM, означает двойные стандарты, которые не должны терпеться.
Кто может гарантировать, что что-то вроде ContentFilterExclusionList не вернётся тихо в одном из будущих обновлений?
Мы считаем, что Apple нельзя доверять наши данные. Именно поэтому мы создали Raspberry Pi Ethernet Gadget — портативное внешнее устройство для фильтрации сети, предназначенное для того, чтобы максимально усложнить сбор данных.
Как справедливо отмечает Джеффри Пол: ваш компьютер — не ваш.
Но он должен быть вашим!
21 февраля 2025 года Apple отключила функцию расширенной защиты данных (ADP) для пользователей из Великобритании, вероятно, в ответ на секретное распоряжение правительства Великобритании, известное как Technical Capability Notice, выданное в рамках Закона о следственных полномочиях 2016 года. Уже 7 февраля 2025 года The Washington Post сообщила об утекшем документе, в котором предсказывался шаг Apple. В соответствии с требованиями Apple перестала предлагать ADP новым пользователям из Великобритании и объявила о планах отключить её для существующих пользователей. Этот шаг, вероятно, направлен на защиту пользователей Apple по всему миру, поскольку британские надзорные органы требуют доступа к зашифрованным резервным копиям Apple во всём мире.
Даже Google не может ни подтвердить, ни опровергнуть получение такого распоряжения, что указывает на то, что компания также получила аналогичное Technical Capability Notice.
«Правительство Великобритании предоставило себе возможность отправлять компаниям по всему миру уведомления, обязывающие их тайно подрывать безопасность своих пользователей, продуктов или услуг. Компания не может никому об этом рассказать, она даже не может публично признать, что получила такое уведомление. Она не может выразить несогласие, не может предупредить пользователей о том, что они пострадали, и не может оспорить это решение в открытом суде, потому что секретный приказ — это секрет. Это уведомление затрагивает миллионы людей, которые не имеют права узнать о его существовании».
Apple подала апелляцию в Трибунал по следственным полномочиям, оспаривая законность распоряжения правительства. Результат этой апелляции может иметь значительные последствия для конфиденциальности пользователей и объёма полномочий правительства в области надзора в Великобритании.
Однако это фактически означает, что все данные, хранящиеся в облаке пользователями из Великобритании, больше не защищены сквозным шифрованием. Вместо этого Apple хранит ключи шифрования, что означает, что компания должна передать их по требованию ордера.
Это не просто изменение политики: это прямая атака на шифрование и конфиденциальность в интернете в целом.
Privacy International:
https://privacyinternational.org/news-analysis/5530/apple-and-long-secret-arm-uk-government
https://privacyinternational.org/explainer/5531/pis-opinion-how-uk-government-making-security-harder-everyone
The Washington Post:
https://www.washingtonpost.com/technology/2025/02/07/apple-encryption-backdoor-uk/
Heise Online:
https://www.heise.de/en/news/Even-Google-cannot-deny-the-British-surveillance-order-10318847.html
Джеффри Пол:
https://sneak.berlin/20201112/your-computer-isnt-yours/#updates
Apple:
https://www.apple.com/ru/privacy/
https://www.apple.com/ru/legal/transparency/
PRISM и CLOUD Act:
https://ru.wikipedia.org/wiki/PRISM
https://www.reuters.com/article/us-apple-fbi-icloud-exclusive/exclusive-apple-dropped-plan-for-encrypting-backups-after-fbi-complained-sources-idUSKBN1ZK1CT
https://ru.wikipedia.org/wiki/CLOUD_Act
Objective Development:
https://blog.obdev.at/a-wall-without-a-hole/
https://blog.obdev.at/a-hole-in-the-wall/
GOING DARK: Это устройство для конфиденциальности на базе Raspberry Pi работает как портативный маршрутизатор, давая вам полный контроль над всем сетевым трафиком, включая собственные процессы Apple. Следуя нашему руководству, Wi-Fi вашего Mac будет полностью отключён. Вместо этого он будет подключаться к Raspberry Pi через USB-C, а Raspberry Pi будет управлять интернет-соединением.
1) РЕЖИМ 1: Фильтрация на уровне сети с AdGuardHome
В этом режиме ваше Ethernet-устройство фильтрует весь трафик через AdGuardHome — самовозводимый DNS-сервер, предназначенный для блокировки рекламы, трекеров и вредоносных доменов во всей сети. Для дополнительной конфиденциальности мы настраиваем Unbound как апстрим-резолвер DNS, что гарантирует, что ваши запросы разрешаются конфиденциально без зависимости от сторонних DNS-провайдеров. Кроме того, мы устанавливаем обширные списки блокировки, включая наш собственный «Ультимативный список блокировки Apple», который блокирует все домены, принадлежащие Apple. ПРЕДУПРЕЖДЕНИЕ: активация этого списка нарушит работу сервисов и программ Apple. Продолжайте с осторожностью.
2) РЕЖИМ 2: Зашифрованный VPN-туннель с WireGuard (необязательная настройка)
В этом режиме вы можете использовать Raspberry Pi как клиент WireGuard, что позволяет установить защищённый зашифрованный VPN-туннель. Вы можете подключиться к домашнему маршрутизатору (РЕКОМЕНДУЕТСЯ, если на нём установлен и настроен WireGuard) или к любому другому серверу WireGuard на ваш выбор (НЕ РЕКОМЕНДУЕТСЯ). Даже с включённым VPN AdGuardHome будет продолжать фильтровать рекламу и трекеры перед передачей DNS-запросов через зашифрованный туннель. Это обеспечивает как конфиденциальность, так и безопасность, сохраняя полную блокировку рекламы на уровне сети.
3) РЕЖИМ 3: Прозрачный прокси Tor
В этом режиме весь ваш интернет-трафик маршрутизируется через прозрачный прокси Tor, обеспечивая анонимность за счёт передачи соединений через сеть Tor. Даже в этой настройке AdGuardHome продолжает фильтровать рекламу и трекеры перед тем, как трафик попадает в сеть Tor, что улучшает конфиденциальность и сокращает ненужные соединения. Важное замечание: это не обязательно рекомендуемый подход для анонимности. Если ваша цель — частный просмотр веб-страниц, strongly рекомендуется использовать Tor Browser, так как он предоставляет дополнительные средства защиты, недоступные для прозрачного прокси.
4) Поддержка беспроводной точки доступа
Помимо подключения Mac через USB, ваше устройство для конфиденциальности на базе Raspberry Pi может также работать как беспроводная точка доступа, позволяя другим устройствам (например, смартфонам) подключаться и использовать РЕЖИМ 1, РЕЖИМ 2 или РЕЖИМ 3 для повышения конфиденциальности и безопасности. Важное замечание: если вы хотите подключить Raspberry Pi к Wi-Fi-сети, одновременно работая в режиме точки доступа, вам потребуется дополнительный Wi-Fi-адаптер. Для этого руководства мы используем ALFA AWUS036ACM, который работает «из коробки» и обеспечивает стабильное двухдиапазонное Wi-Fi-соединение.
5) Усиленная безопасность
Чтобы обеспечить максимальную безопасность, мы внедряем несколько уровней защиты: - Защита межсетевым экраном с помощью nftables – мы настраиваем nftables как надёжный межсетевой экран, динамически управляемый через диспетчер NetworkManager для плавного переключения между РЕЖИМОМ 1, РЕЖИМОМ 2 и РЕЖИМОМ 3, обеспечивая безопасную и стабильную работу. - Упрочнённая конфигурация SSH – безопасный доступ обеспечивается благодаря тщательно защищённой настройке SSH, что снижает векторы атак и улучшает общую целостность системы. - Контроль доступа пользователей – мы создаём отдельные учётные записи администратора и стандартного пользователя, следуя лучшим практикам безопасности, чтобы ограничить привилегии и снизить риски. - Автоматические обновления безопасности – неконтролируемые обновления гарантируют, что критически важное программное обеспечение остаётся актуальным, минимизируя уязвимости и повышая устойчивость системы.
6) Случайная идентификация устройства
Каждый раз, когда вы подключаетесь к общественной сети Wi-Fi, в журналах будет фиксироваться только идентификатор Ethernet-гаджета Raspberry Pi, а не вашего Mac. Это предотвращает возможность отслеживания вашего реального устройства операторами сети.
Для дальнейшего улучшения конфиденциальности:
Эти меры гарантируют, что ваш цифровой след остаётся максимально анонимным при подключении к общественным сетям.
7) NTP-сервер с уважением к конфиденциальности
Чтобы поддерживать точное системное время, не жертвуя конфиденциальностью, мы настраиваем Ethernet-гаджет Raspberry Pi для использования NTP-серверов, уважающих конфиденциальность, с ntppool.org.
Основные функции: - Синхронизация времени с акцентом на конфиденциальность – обеспечивает обновление системного времени через доверенные NTP-серверы, избегая централизованных источников времени, нарушающих конфиденциальность. - Расширенная поддержка автономной работы – настроена для обработки длительных периодов простоя, что позволяет устройству подключаться к интернету даже после длительного отключения. - Локальный сервер времени для подключённых устройств – клиенты, использующие Ethernet-гаджет Raspberry Pi, могут синхронизировать системное время напрямую с встроенного NTP-сервера Pi. - Необязательно: для ещё большей надёжности мы рекомендуем установить аппаратные часы (модуль RTC), чтобы избежать проблем с синхронизацией.
8) Локальный веб-интерфейс
Для упрощения управления мы настраиваем локальный веб-интерфейс, который позволяет вам:
Этот интуитивно понятный интерфейс обеспечивает удобное управление вашим Ethernet-гаджетом Raspberry Pi, позволяя легко настраивать параметры прямо из браузера.
Для этой настройки мы используем Raspberry Pi 4B (8 ГБ). Чтобы обеспечить стабильную работу, важно использовать высококачественный кабель USB-C, поддерживающий быструю передачу данных. Кроме того, мы используем ALFA AWUS036ACM. Если вы выберете другой внешний Wi-Fi-адаптер, убедитесь, что он совместим с Raspberry Pi OS, и обновите имя интерфейса в этом руководстве соответственно! Надёжная карта microSD критически важна для плавной работы. Избегайте дешёвых, низкокачественных брендов. Мы настоятельно рекомендуем карты SanDisk с рейтингом A1, так как они предлагают отличную производительность. Карты microSD с высокой износостойкостью также являются отличным вариантом — они достаточно быстрые и обеспечивают превосходную долговечность на основе нашего опыта. Карта объёмом 32 ГБ более чем достаточна для этой настройки.
Активная система охлаждения для предотвращения перегрева, особенно в жаркие летние дни. Мы рекомендуем EP-0163 Ice Tower для эффективного охлаждения. Модуль часов реального времени (RTC), такой как RV3028, полезен для поддержания точной синхронизации времени, особенно когда Raspberry Pi остаётся выключенным или отключённым от сети в течение длительного времени. Он аккуратно размещается рядом с EP-0163 Ice Tower.
1. Скачайте и установите Raspberry Pi Imager
3. Обновите систему
4. Дополнительные настройки
Однако, если вам интересно, вы можете ознакомиться с:
Настройки Z-Ram: эти оптимизации могут улучшить производительность системы, особенно на устройствах с небольшим объёмом оперативной памяти.
Настройки MOTD: настройка сообщения дня (MOTD) может улучшить опыт входа в систему, отображая полезную информацию о системе. Обе настройки не обязательны, но могут быть полезны.
ОТКЛЮЧЕНИЕ СВЕТОДИОДОВ: отключите все светодиоды, и ваш Raspberry Pi будет работать полностью в тёмном режиме, без каких-либо индикаторов состояния.
Пропустите разделы по управлению доступом пользователей, защите SSH и настройке межсетевого экрана. Эти вопросы будут полностью освещены в данном руководстве!
Чтобы настроить Raspberry Pi, откройте инструмент настройки Raspberry Pi, выполнив:
sudo raspi-config
1. Расширение файловой системы
2. Включение предсказуемых имён сетевых интерфейсов
Мы работаем со встроенным Wi-Fi (wlan0) и внешним Wi-Fi-адаптером (wlx00c0caae6319), что является предсказуемым именем интерфейса для ALFA AWUS036ACM. Включив предсказуемые имена сетевых интерфейсов, мы можем надёжно различать встроенный и внешний Wi-Fi-адаптеры. Без этой настройки внешняя Wi-Fi-карта может иногда получать имя wlan0 вместо встроенного Wi-Fi, что может вызвать проблемы с настройками межсетевого экрана и маршрутизации.
Мы создаём отдельные учётные записи администратора и стандартного пользователя, следуя лучшим практикам безопасности, чтобы ограничить привилегии и снизить риски. Учётная запись администратора (admin) предназначена для обслуживания и настройки системы, а учётная запись стандартного пользователя (term7) используется для повседневных задач с минимальными правами.
Следуя принципу минимальных привилегий (PoLP), мы повышаем безопасность и минимизируем потенциальные векторы атак: эта настройка позволяет отключить вход от имени root через SSH, добавляя дополнительный уровень защиты. Даже если злоумышленник получит доступ, у него не будет прав администратора по умолчанию, что значительно снижает риск компрометации системы.
Чтобы создать выделенную учётную запись администратора, выполните следующую команду:
sudo adduser admin
Единственная обязательная деталь — надёжный пароль. Мы настоятельно рекомендуем использовать менеджер паролей, например KeePassXC, для безопасного хранения и управления вашими учётными данными.
Если вы предпочитаете сгенерировать надёжный пароль прямо из командной строки, используйте:
openssl rand -base64 48 | cut -c1-32
Эта команда генерирует 32-символьный случайный пароль с помощью генератора случайных чисел OpenSSL, который соответствует стандартам NIST SP 800-90A/B/C и использует ChaCha20 (или AES-CTR в более старых версиях), обеспечивая криптографическую стойкость. Результат непредсказуем и устойчив к атакам грубой силы.
После создания пользователя-администратора добавьте его во все необходимые группы, чтобы он имел доступ к требуемым функциям системы:
sudo usermod -a -G adm,tty,dialout,cdrom,audio,video,plugdev,games,users,input,netdev,gpio,i2c,spi,sudo,term7 admin
Чтобы повысить безопасность, удалите права sudo у пользователя term7 и передайте их пользователю admin, при этом убедившись, что sudo теперь требует ввода пароля:
sudo sed -i 's/term7/admin/g' /etc/sudoers.d/010_pi-nopasswd
sudo sed -i 's/NOPASSWD: //g' /etc/sudoers.d/010_pi-nopasswd
Чтобы повысить безопасность, удалим стандартного пользователя (в этом примере — term7) из группы sudo, чтобы у него больше не было административных привилегий. Сначала войдите в систему под новым учётной записью администратора:
su admin
Теперь выполните следующую команду, чтобы удалить term7 из группы sudo (замените term7 на ваше фактическое имя стандартного пользователя):
sudo deluser term7 sudo
Хотя у term7 больше нет полного доступа sudo, мы хотим разрешить ему перезагружать и выключать Raspberry Pi без переключения на администратора. Выполните следующую команду, чтобы создать новый файл политики sudo:
echo "term7 ALL = NOPASSWD: /usr/sbin/reboot, /usr/sbin/shutdown" | sudo tee /etc/sudoers.d/common_users > /dev/null
Это предоставляет term7 доступ без пароля к командам перезагрузки и выключения.
Если вы хотите разрешить дополнительные команды без требования sudo, просто отредактируйте файл: /etc/sudoers.d/common_users
По умолчанию вы всё ещё можете подключаться по SSH напрямую к учётной записи администратора, что является риском для безопасности. Чтобы усилить безопасность SSH, мы изменим его конфигурацию.
Усиление порта - Изменение стандартного порта SSH (на порт 6666)
Сильные криптографические алгоритмы:
- Шифры для надёжного шифрования (chacha20-poly1305, aes256-gcm)
- Безопасный обмен ключами (curve25519-sha256, diffie-hellman-group16-sha512)
- MAC для защиты от криптографических уязвимостей (hmac-sha2-512-etm)
Строгий контроль аутентификации
- Отключение прямого входа под root
- Ограничение доступа по SSH для определённых пользователей (term7)
- Ограничение попыток аутентификации и сессий (MaxAuthTries 2, MaxSessions 2)
- Принудительная аутентификация по SSH-ключу
- Отключение входа по паролю
- Отключение аутентификации с запросом-ответом (предотвращает атаки перебора)
Усиление сессий
- Контроль времени ожидания и бездействия (ClientAliveInterval 300, ClientAliveCountMax 2)
- Запрет входа с пустым паролем
Расширенное ведение журнала и мониторинг - Ведение журнала: фиксация неудачных попыток аутентификации, IP-адресов и подозрительных действий - Включение предупреждающего баннера
Аутентификация по SSH-ключу безопаснее, чем аутентификация по паролю. Она использует пару криптографических ключей:
Закрытый ключ → Хранится в безопасности на вашем Mac.
Открытый ключ → Копируется на ваш Raspberry Pi.
После настройки только ваш Mac сможет подключаться к Raspberry Pi — если только ваш закрытый ключ не скомпрометирован.
Откройте Terminal на вашем Mac и выполните:
ssh-keygen -t ed25519 -C "your_email@example.com"
Используется алгоритм Ed25519, который быстрее и безопаснее, чем RSA. Пожалуйста, укажите свой реальный адрес электронной почты для справки.
Расширенная безопасность
Для ещё более надёжной настройки рассмотрите возможность использования аппаратного ключа безопасности, например Nitrokey или YubiKey. Однако для них требуется дополнительная настройка, что выходит за рамки этого руководства. Возможно, мы рассмотрим их в отдельном руководстве в будущем.
Выполните эту команду, заменив 192.168.1.123 на фактический локальный IP-адрес вашего Raspberry Pi:
ssh-copy-id -i ~/.ssh/id_ed25519.pub term7@192.168.1.123
Если ssh-copy-id не установлен в macOS, скопируйте ключ вручную с помощью:
cat ~/.ssh/id_ed25519.pub | ssh term7@192.168.1.123 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'
Всё ещё на вашем Mac, отредактируйте файл конфигурации SSH:
nano ~/.ssh/config
Убедитесь, что эта строка присутствует: IdentityFile ~/.ssh/id_ed25519
Это гарантирует, что ваш Mac всегда будет использовать правильный закрытый ключ (id_ed25519) для аутентификации и предотвратит запрос пароля SSH, если аутентификация по ключу настроена правильно.
После настройки аутентификации по SSH-ключу необходимо установить правильные разрешения для каталога .ssh и файла authorized_keys, чтобы SSH работал безопасно:
ssh term7@192.168.1.123
Замените 192.168.1.123 на фактический IP-адрес вашего Raspberry Pi!
В учётной записи стандартного пользователя выполните следующие команды на вашем Raspberry Pi:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Это гарантирует, что только пользователь (term7) имеет доступ к каталогу .ssh и что только пользователь может читать и записывать файл authorized_keys.
Теперь войдите в учётную запись администратора:
su admin
Чтобы отображать предупреждающий баннер безопасности перед входом, скачайте и замените файл /etc/issue.net нашей предварительно настроенной версией из репозитория:
sudo curl -L -o /etc/issue.net "https://codeberg.org/term7/Going-Dark/raw/branch/main/Pi%20Configuration%20Files/ssh/issue.net"
sudo nano /etc/issue.net
Самый быстрый способ упрочнить конфигурацию SSH — заменить её нашим предварительно настроенным файлом из этого репозитория.
Однако перед внесением изменений создайте резервную копию, чтобы не остаться без доступа в случае ошибки. Выполните эту команду для создания резервной копии:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
Если что-то пойдёт не так, вы сможете восстановить исходный файл. Чтобы загрузить нашу упрочнённую конфигурацию, выполните команду:
sudo curl -L -o /etc/ssh/sshd_config "https://codeberg.org/term7/Going-Dark/raw/branch/main/Pi%20Configuration%20Files/ssh/sshd_config"
Это перезапишет ваш текущий стандартный файл конфигурации SSH. ВАЖНО: если вы используете стандартное имя пользователя, отличное от term7, вам нужно обновить эту строку: AllowUsers term7
Чтобы проверить и отредактировать файл перед применением изменений, откройте его в Nano:
sudo nano /etc/ssh/sshd_config
Найдите и замените term7 на ваше фактическое имя пользователя, затем сохраните (CTRL + X, затем Y, затем Enter).
После внесения необходимых изменений перезапустите службу SSH:
sudo systemctl restart ssh
НЕ выходите из системы! На вашем Mac откройте новое окно терминала и проверьте доступ по SSH:
ssh term7@192.168.1.123 -p 6666
Не забудьте заменить 192.168.1.123 на фактический IP-адрес вашего Raspberry Pi!
Если подключение работает нормально, ваша новая упрочнённая конфигурация SSH успешно применена!
Поскольку вы всё ещё вошли в систему в исходном окне терминала, вы сможете устранить любые проблемы, если что-то не работает.
Если что-то пойдёт не так и вы останетесь без доступа, восстановите резервную копию. Получите доступ к вашему Raspberry Pi локально (используйте клавиатуру и монитор). Затем введите следующие команды:
sudo cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
sudo systemctl restart ssh
Это восстановит вашу предыдущую рабочую конфигурацию SSH.
Поддержание вашего Raspberry Pi в актуальном состоянии критически важно для безопасности и стабильности. Вместо ручного обновления мы настраиваем автоматические обновления для установки обновлений безопасности и системы. Поскольку наш Raspberry Pi включается только когда мы работаем на Mac, нам нужно убедиться, что обновления запускаются после каждой перезагрузки. Кроме того, так как мы установим AdGuardHome (которому требуется время для применения списков фильтров), мы вводим задержку в 2 минуты перед началом процесса обновления.
Чтобы настроить автоматические обновления, используйте следующую команду для установки необходимых пакетов:
sudo apt install -y unattended-upgrades apt-listchanges
По умолчанию обновления безопасности Debian включены. Однако нам нужно вручную добавить обновления Raspberry Pi. Выполните эту команду, чтобы изменить файл 50unattended-upgrades:
sudo sed -i '/"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";/a\
"origin=Raspbian,codename=${distro_codename},label=Raspbian";\
"origin=Raspberry Pi Foundation,codename=${distro_codename},label=Raspberry Pi Foundation";' /etc/apt/apt.conf.d/50unattended-upgrades
Также разрешите автоматическое обновление пакетов из репозитория Debian:
sudo sed -i 's|^//\s*\("origin=Debian,codename=\${distro_codename}-updates"\);|\1;|' /etc/apt/apt.conf.d/50unattended-upgrades
Автоматическое удаление ненужных зависимостей:
sudo sed -i 's|^//\s*Unattended-Upgrade::Remove-Unused-Dependencies\s*"false";|Unattended-Upgrade::Remove-Unused-Dependencies "true";|' /etc/apt/apt.conf.d/50unattended-upgrades
Создайте таймер systemd, который будет ждать 2 минуты после загрузки перед запуском обновлений:
echo '[Unit]
Description=Unattended Upgrades Timer
[Timer]
OnBootSec=2min
Unit=unattended-upgrades.service
[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/unattended-upgrades.timer > /dev/null
Это предотвращает слишком ранний запуск обновлений, пока AdGuardHome ещё инициализируется.
Теперь создайте службу systemd, которая будет выполнять автоматические обновления:
echo '[Unit]
Description=Unattended Upgrades
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/bin/unattended-upgrade -d
[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/unattended-upgrades.service > /dev/null
Чтобы активировать таймер и службу systemd, выполните:
sudo systemctl daemon-reload
sudo systemctl enable unattended-upgrades.timer
sudo systemctl start unattended-upgrades.timer
После перезагрузки проверьте, активен ли таймер:
systemctl list-timers --all | grep unattended-upgrades
Если вы видите запись, таймер работает.
Чтобы проверить, были ли применены обновления, просмотрите журналы автоматических обновлений:
journalctl -u unattended-upgrades --no-pager
Хотя IPv6 предлагает преимущества, использование как IPv4, так и IPv6 (двойной стек) значительно усложняет настройку межсетевого экрана и увеличивает риски безопасности.
Поскольку нам не нужен IPv6, мы полностью отключим его, чтобы улучшить безопасность и упростить сетевые настройки.
Навсегда отключите IPv6, изменив файл /etc/sysctl.conf:
echo -e "\n# Disable IPv6:\nnet.ipv6.conf.all.disable_ipv6 = 1\nnet.ipv6.conf.default.disable_ipv6 = 1\nnet.ipv6.conf.lo.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf > /dev/null
Измените параметры загрузки в файле /boot/firmware/cmdline.txt, чтобы предотвратить загрузку IPv6 при старте:
sudo sed -i 's/$/ ipv6.disable=1/' /boot/firmware/cmdline.txt
Чтобы изменения вступили в силу, перезагрузите систему:
sudo reboot now
Так как IPv6 теперь отключён, удалите все локальные IPv6-адреса из /etc/hosts, чтобы предотвратить ненужные попытки разрешения:
sudo sed -i '/::/d' /etc/hosts
По умолчанию современная Raspberry Pi OS использует NetworkManager для управления сетевыми интерфейсами, DHCP и настройками Wi-Fi. Чтобы улучшить конфиденциальность и снизить риск отслеживания, мы включим встроенную функцию рандомизации MAC-адресов в NetworkManager.
Создайте файл конфигурации, чтобы включить случайные MAC-адреса для Wi-Fi и Ethernet:
echo '[device]
wifi.scan-rand-mac-address=yes
[connection]
wifi.cloned-mac-address=random
ethernet.cloned-mac-address=random
connection.stable-id=${CONNECTION}/${BOOT}' | sudo tee /etc/NetworkManager/conf.d/00-randomize.conf > /dev/null
Чтобы убедиться, что MAC-адрес изменяется динамически, выполните:
sudo nmcli device show | grep GENERAL.HWADDR
Теперь перезагрузите Raspberry Pi:
sudo reboot now
После перезагрузки системы войдите в Raspberry Pi (ещё раз проверьте, какой IP-адрес был назначен — скорее всего, он изменится после смены MAC-адреса!) и снова выполните следующую команду:
sudo nmcli device show | grep GENERAL.HWADDR
Если MAC-адрес отличается от предыдущего вывода, настройка рандомизации работает корректно.
⚠️ ВАЖНО: Побочный эффект рандомизации MAC-адреса заключается в том, что ваш маршрутизатор может назначить другой IP-адрес вашему Raspberry Pi. Если вы используете SSH, возможно, потребуется проверить новый IP-адрес Raspberry Pi и обновить подключение SSH соответственно.
Многие сети фиксируют имена устройств (hostname) вместе с MAC-адресами и IP-адресами. Если имя устройства остаётся статичным, это создаёт уникальный отпечаток, который можно использовать для отслеживания устройства в разных сетях. Это означает, что даже если рандомизация MAC-адреса включена, фиксированное имя устройства всё равно может использоваться для его идентификации. Поэтому мы используем английский словарь, чтобы выбирать случайное слово для Raspberry Pi при каждой перезагрузке до подключения к сети.
Сначала создадим папки для хранения скриптов и словаря:
[ -d ~/tools ] || mkdir ~/tools && [ -d ~/tools/dict ] || mkdir ~/tools/dict
[ -d ~/script ] || mkdir ~/script && [ -d ~/script/randhost ] || mkdir ~/script/randhost
Скачайте и распакуйте английский словарь UK:
curl -L https://codeberg.org/term7/Going-Dark/raw/branch/main/misc/Dictionary/ukenglish.zip -o ~/tools/dict/ukenglish.zip && unzip -o ~/tools/dict/ukenglish.zip -d ~/tools/dict/ && rm ~/tools/dict/ukenglish.zip
Создайте скрипт для рандомизации имени устройства:
echo '#!/bin/bash
# Random Hostname Generator
ALL_NON_RANDOM_WORDS=/home/admin/tools/dict/ukenglish.txt
# Count the number of words in the dictionary
non_random_words=$(wc -l < "$ALL_NON_RANDOM_WORDS")
# Generate a random index and select a word
WORD_INDEX=$(od -N3 -An -i /dev/urandom | awk -v r="$non_random_words" "{print int(1 + r * \$1 / 16777216)}")
NEW_HOSTNAME=$(sed -n "${WORD_INDEX}p" "$ALL_NON_RANDOM_WORDS")
# Change Static Hostname
hostnamectl set-hostname "$NEW_HOSTNAME"
# Update /etc/hosts safely
sed -i "/127.0.1.1/c\127.0.1.1 $NEW_HOSTNAME" /etc/hosts' | sudo tee /home/admin/script/randhost/hostname.sh > /dev/null
Убедитесь, что у скрипта правильные владельцы и права доступа:
sudo chmod 700 /home/admin/script/randhost/hostname.sh
sudo chown root:root /home/admin/script/randhost/hostname.sh
echo '[Unit]
Description=Random Hostname Generator
Wants=network-pre.target
After=network-pre.target
[Service]
Type=oneshot
ExecStart=/usr/bin/bash /home/admin/script/randhost/hostname.sh
RemainAfterExit=yes
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/hostname.service > /dev/null
Включите службу:
sudo systemctl daemon-reload
sudo systemctl enable hostname.service
Вручную запустите службу:
sudo systemctl start hostname.service
Проверьте текущее имя устройства:
hostname
Если вы видите другое имя устройства, чем раньше, настройка работает корректно. Теперь ваш Raspberry Pi будет случайным образом выбирать новое имя устройства из словаря при каждой перезагрузке.
В этом разделе мы настроим ваш Raspberry Pi как USB-C Ethernet гаджет, что позволит ему делиться интернет-подключением с компьютером через USB.
Чтобы настроить Raspberry Pi как USB-C Ethernet гаджет, необходимо:
Чтобы включить режим гаджета Ethernet, нужно активировать контроллер DWC2 USB и настроить параметры загрузки ядра. Добавьте необходимый оверлей в /boot/firmware/config.txt:
sudo sed -i '$a\dtoverlay=dwc2,dr_mode=peripheral' /boot/firmware/config.txt
Измените /boot/firmware/cmdline.txt, чтобы загрузить необходимые модули ядра:
sudo sed -i 's/$/ rootwait modules-load=dwc2,g_ether quiet/' /boot/firmware/cmdline.txt
По умолчанию NetworkManager может игнорировать интерфейс гаджета (usb0). Нам нужно изменить правила udev, чтобы разрешить это. Сначала скопируйте и измените необходимые правила udev:
sudo cp /usr/lib/udev/rules.d/85-nm-unmanaged.rules /etc/udev/rules.d/85-nm-unmanaged.rules
Затем обновите правило, чтобы NetworkManager управлял usb0:
sudo sed -i '/ENV{DEVTYPE}=="gadget"/s/ENV{NM_UNMANAGED}="1"/ENV{NM_UNMANAGED}="0"/' /etc/udev/rules.d/85-nm-unmanaged.rules
Мы назначим статический IP (192.168.77.1/24) интерфейсу usb0 и включим общий доступ к сети.
Создайте и настройте интерфейс:
sudo nmcli con add type ethernet ifname usb0 con-name usb0-static
sudo nmcli con modify usb0-static ipv4.addresses 192.168.77.1/24 ipv4.method shared
sudo nmcli con modify usb0-static connection.autoconnect yes connection.autoconnect-priority 50
Так как IPv6 отключён глобально, отключите его и для этого интерфейса:
sudo nmcli connection modify usb0-static ipv6.method disable
Обеспечьте стабильный MAC-адрес для usb0 — единственного интерфейса, для которого мы не хотим рандомизации MAC:
sudo nmcli connection modify usb0-static ethernet.cloned-mac-address permanent
Чтобы разрешить общий доступ к интернету с Raspberry Pi через Wi-Fi на подключённый компьютер, включите пересылку IPv4. Измените файл /etc/sysctl.conf:
sudo sed -i 's/^#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
Это позволяет пересылку пакетов, давая Raspberry Pi возможность предоставлять доступ к интернету через usb0.
Чтобы все изменения вступили в силу, перезагрузите Raspberry Pi:
sudo reboot now
После перезагрузки ваш Raspberry Pi должен работать как USB-C Ethernet-гаджет через USB.
Подключитесь к Raspberry Pi, используя статический IP-адрес, назначенный интерфейсу usb0:
ssh term7@192.168.77.1 -p 6666
Проверьте подключение на вашем компьютере: перейдите в Настройки системы → Сеть и найдите RNDIS/Ethernet-гаджет. Вы должны увидеть зелёную точку с статусом: Подключено.
Поскольку ваш Raspberry Pi подключён к интернету через домашний маршрутизатор, ваш компьютер теперь должен получать доступ к интернету через Raspberry Pi. Отключите Wi-Fi на вашем Mac и проверьте, остаётся ли интернет-соединение.
В этой настройке мы хотим сконфигурировать wlan0 как беспроводную точку доступа, которую можно запускать вручную, а не запускать постоянно. Это даёт больший контроль над доступностью сети и помогает оптимизировать производительность системы.
Поскольку мы не хотим использовать wlan0 для доступа к интернету, мы настроим наш внешний Wi-Fi-адаптер — ALFA AWUS036ACM — для обработки интернет-соединения.
ALFA AWUS036ACM обеспечивает значительно более высокую пропускную способность по сравнению со встроенным Wi-Fi Raspberry Pi (wlan0), особенно при подключении к порту USB 3.0. Использование внешнего адаптера гарантирует более высокую скорость и улучшенную стабильность, что делает его предпочтительным выбором для подключения к интернету.
Поскольку мы включили предсказуемые имена сетевых интерфейсов (см. 03 - ПРЕДВАРИТЕЛЬНЫЕ УСЛОВИЯ), наш внешний Wi-Fi-адаптер получает имя интерфейса: wlx00c0caae6319
⚠️ Важно: Если вы используете другой внешний Wi-Fi-адаптер, его имя интерфейса будет другим. Вам следует заменить wlx00c0caae6319 на фактическое имя вашего интерфейса во всём этом руководстве, во всех файлах конфигурации межсетевого экрана и любых сетевых командах или настройках.
Перед продолжением убедитесь, что ваш внешний Wi-Fi-адаптер подключён и правильно соединён с Raspberry Pi. Чтобы узнать имя интерфейса ваших Wi-Fi-адаптеров, выполните следующую команду:
nmcli device status
Найдите ваш внешний Wi-Fi-адаптер в выводе. Обычно у него будет имя, начинающееся с wlx или wlan. Если вы не уверены, какой из них ваш внешний адаптер, сравните его со встроенным Wi-Fi (wlan0). У внешнего будет другое имя.
Чтобы стандартизировать имена подключений, выполните:
sudo nmcli con modify preconfigured connection.id "Wi-Fi"
sudo nmcli con modify "Wired connection 1" connection.id "Ethernet"
Отключите IPv6 для обоих подключений:
sudo nmcli connection modify Ethernet ipv6.method disable
sudo nmcli connection modify Wi-Fi ipv6.method disable
Измените Wi-Fi-подключение для использования внешнего адаптера:
sudo nmcli con down Wi-Fi
sudo nmcli con modify Wi-Fi ifname wlx00c0caae6319
⚠️ Предупреждение: Используйте фактическое предсказуемое имя интерфейса вашего собственного Wi-Fi-адаптера!
Запустите внешнее Wi-Fi-подключение:
sudo nmcli con up Wi-Fi
Теперь ваш внешний Wi-Fi-адаптер должен обрабатывать интернет-соединение вместо wlan0.
Добавьте новое подключение точки доступа (SSID: ONION):
sudo nmcli con add con-name Hotspot ifname wlan0 type wifi ssid "ONION"
Настройте точку доступа как точку доступа с общим доступом к сети:
sudo nmcli con modify Hotspot 802-11-wireless.mode ap 802-11-wireless.band bg ipv4.method shared
sudo nmcli con modify Hotspot ipv4.addresses 192.168.37.1/24
Настройте защиту Wi-Fi для точки доступа:
sudo nmcli con modify Hotspot wifi-sec.key-mgmt wpa-psk
sudo nmcli con modify Hotspot wifi-sec.proto rsn
sudo nmcli con modify Hotspot wifi-sec.pairwise ccmp
sudo nmcli con modify Hotspot wifi-sec.group ccmp
sudo nmcli con modify Hotspot wifi-sec.auth-alg open
sudo nmcli con modify Hotspot wifi-sec.pmf optional
sudo nmcli con modify Hotspot wifi-sec.psk "your-own-strong-wifi-password"
Отключите IPv6 для точки доступа:
sudo nmcli connection modify Hotspot ipv6.method disable
Запретите автоматическое подключение при запуске:
sudo nmcli connection modify Hotspot connection.autoconnect no
Точка доступа теперь настроена, но будет запускаться только при ручном включении.
Чтобы запустить точку доступа:
sudo nmcli con up Hotspot
Чтобы остановить точку доступа:
sudo nmcli con down Hotspot
Ваш Raspberry Pi теперь работает как управляемая вручную беспроводная точка доступа.
После запуска точки доступа вы можете подключить свой смартфон или другие устройства, используя:
По умолчанию Raspberry Pi синхронизирует время с помощью серверов NTP из пула Debian. Однако мы хотим настроить локальный NTP-сервер на Raspberry Pi, чтобы обеспечивать синхронизацию времени для подключённых клиентов. Кроме того, мы настроим наше устройство на использование внешних NTP-серверов, уважающих конфиденциальность, из проекта NTP Pool Project, чтобы гарантировать точную и безопасную синхронизацию времени. Таким образом, наш Mac будет синхронизировать время через Raspberry Pi, а не обращаться к time.apple.com, что дополнительно ограничивает способность Apple отслеживать наше устройство по запросам синхронизации времени.
Подробнее: Проект NTP Pool
Сначала установите пакет NTP. Это автоматически удалит systemd-timesyncd — стандартную службу синхронизации времени на Raspberry Pi:
sudo apt install -y ntp
Чтобы упростить настройку, загрузите предварительно настроенный файл конфигурации NTP из нашего репозитория:
sudo curl -L -o /etc/ntpsec/ntp.conf "https://codeberg.org/term7/Going-Dark/raw/branch/main/Pi%20Configuration%20Files/ntp/ntp.conf"
Эта конфигурация:
- Настраивает Raspberry Pi как NTP-сервер для клиентов локальной сети.
- Использует несколько внешних серверов времени для отказоустойчивости.
- Предотвращает серьезные проблемы с синхронизацией времени после длительных периодов отключения от сети.
Если Raspberry Pi остаётся отключённым от сети в течение длительного времени, его внутренние часы могут значительно отставать или спешить. Наши текущие настройки предотвращают отказ NTP от использования собственных локальных часов после длительного простоя. Без этих настроек большое расхождение во времени могло бы привести к невозможности подключения Raspberry Pi к интернету.
Если Raspberry Pi теряет доступ к интернету, он продолжит предоставлять время локальным клиентам на основе последней успешной синхронизации. Однако со временем могут накапливаться ошибки дрейфа часов, что потенциально повлияет на подключение к интернету и безопасные соединения (например, сертификаты TLS/SSL могут стать недействительными из-за неверного системного времени). Чтобы смягчить эту проблему, мы настоятельно рекомендуем установить модуль часов реального времени (RTC), который отслеживает время даже при отключении питания устройства.
Хотя локальным клиентам разрешено синхронизироваться с Raspberry Pi, они могут по-прежнему отдавать предпочтение внешним NTP-серверам, таким как Apple, Google или Microsoft. Чтобы гарантировать, что все сетевые устройства используют Raspberry Pi для синхронизации времени, позже мы настроим NetworkManager на использование встроенного dnsmasq в качестве DHCP-сервера. Эта настройка передаёт параметры NTP Raspberry Pi всем DHCP-клиентам, обеспечивая их автоматическую синхронизацию времени с Raspberry Pi. Это должно устранить необходимость ручной настройки на каждом устройстве.
Однако, если вы хотите настроить Mac на использование Raspberry Pi в качестве NTP-сервера, откройте новое окно терминала на Mac и временно отключите автоматическую настройку времени:
sudo systemsetup -setusingnetworktime off
Примечание: Эта команда может выдать ошибку ‘Error:-99’ из-за защиты целостности системы Apple (SIP). Однако, несмотря на эту ошибку, наши тесты показали, что настройка всё равно применяется корректно.
Следующая команда — это небольшой хак, так как Apple не документирует поддержку нескольких строк в этой команде. Официально systemsetup -setnetworktimeserver принимает только одну строку. Однако, несмотря на отсутствие документации, этот метод не вызывает ошибок и корректно форматирует файл конфигурации в нашем опыте. Мы хотим настроить Проект NTP Pool в качестве резервных серверов на случай, если Ethernet-гаджет Raspberry Pi недоступен:
sudo systemsetup -setnetworktimeserver "192.168.77.1
server 0.pool.ntp.org
server 1.pool.ntp.org
server 2.pool.ntp.org
server 3.pool.ntp.org"
Если вы предпочитаете избегать этого недокументированного метода, вы можете вручную ввести несколько серверов времени в Настройки системы > Дата и время. Разделяйте каждую запись запятой и заканчивайте точкой, например:
192.168.77.1, 0.pool.ntp.org, 1.pool.ntp.org, 2.pool.ntp.org, 3.pool.ntp.org
Если вы хотите синхронизировать время только через Raspberry Pi и соблюдать корректный синтаксис, документированный Apple, используйте вместо этого команду:
sudo systemsetup -setnetworktimeserver "192.168.77.1"
В конце снова включите автоматическую настройку времени:
sudo systemsetup -setusingnetworktime off
Проверьте, включена ли автоматическая настройка времени:
sudo systemsetup -getusingnetworktime
Чтобы проверить, использует ли macOS правильные настройки, выполните:
sudo systemsetup -getnetworktimeserver
Однако эта команда возвращает только первый сервер из списка!
В этом руководстве мы настроим модуль RTC RV3028. Если вы используете другой модуль RTC, следуйте соответствующим инструкциям по установке. Убедитесь, что вы подключены к вашему Raspberry Pi по SSH и вошли в систему под учётной записью admin.
Установите необходимые пакеты:
sudo apt install -y git python3-smbus
Создайте каталог сборки и перейдите в него:
[ -d ~/build ] || mkdir ~/build && cd ~/build
Клонируйте и установите библиотеку RV3028 для Python:
git clone https://github.com/pimoroni/rv3028-python
cd rv3028-python
sudo ./install.sh --unstable
Переместите примеры скриптов в отдельную папку:
sudo mv ~/Pimoroni/* ~/build/rv3028-python/examples
sudo rm -R /home/admin/Pimoroni
Включите связь по I2C:
sudo sed -i 's/^#dtparam=i2c_arm=on/dtparam=i2c_arm=on/' /boot/firmware/config.txt
Кроме того, чтобы активировать RTC RV3028, нужно загрузить правильный оверлей ядра. Выполните следующую команду, чтобы добавить необходимый оверлей в /boot/firmware/config.txt:
sudo sed -i '0,/^\[all\]/s//&\ndtoverlay=i2c-rtc,rv3028,backup-switchover-mode=1/' /boot/firmware/config.txt
Перезагрузите Raspberry Pi, чтобы изменения вступили в силу:
sudo reboot now
По умолчанию Raspberry Pi использует программные часы, имитирующие аппаратные. Поскольку у нас теперь есть реальный модуль RTC, удалите программные часы, чтобы избежать конфликтов:
sudo apt -y remove fake-hwclock
sudo update-rc.d -f fake-hwclock remove
Наконец, настройте NTP (ntpsec) для получения времени с модуля RTC:
sudo sed -i 's/^#rtcfile \/dev\/rtc0/rtcfile \/dev\/rtc0/' /etc/ntpsec/ntp.conf
Перезапустите NTP, чтобы применить изменения:
sudo systemctl restart ntpsec
⚠ ВАЖНО: Выполнение глав 13–19 шаг за шагом в правильном порядке имеет критическое значение! Любая ошибка в конфигурации может вызвать проблемы с DNS, что приведёт к потере подключения к интернету для вашего Raspberry Pi и подключённых к нему клиентов — или даже полностью заблокирует доступ. Даже небольшие ошибки или пропущенные шаги могут привести к тому, что некоторые аспекты настройки не будут работать должным образом. Действуйте осторожно и точно следуйте каждому шагу.
В этом разделе мы настроим встроенный в NetworkManager Dnsmasq для управления службами DHCP и DNS.
Наши цели:
Правильно настроив Dnsmasq, мы создадим безопасную, конфиденциальную и надёжную локальную систему DNS и DHCP, обеспечивающую стабильную работу и беспрепятственную идентификацию устройств.
Чтобы правильно управлять DHCP и DNS с помощью NetworkManager, сначала нужно настроить его общие параметры, а затем настроить Dnsmasq для стандартных и общих сетевых интерфейсов.
Выполните следующую команду, чтобы создать и обновить /etc/NetworkManager/NetworkManager.conf:
echo '[main]
plugins=ifupdown,keyfile
dns=dnsmasq
dhcp=dnsmasq
[ifupdown]
managed=false' | sudo tee /etc/NetworkManager/NetworkManager.conf > /dev/null
Это гарантирует, что NetworkManager будет использовать Dnsmasq для DHCP и DNS.
NetworkManager использует две разные папки конфигурации для Dnsmasq:
/etc/NetworkManager/dnsmasq.d/) → используется для lo (localhost)./etc/NetworkManager/dnsmasq-shared.d/) → используется для общих сетей, таких как wlan0 и usb0.Нам нужно настроить обе.
Создайте следующий файл конфигурации, чтобы все DNS-запросы перенаправлялись в AdGuardHome и применялись функции безопасности:
echo '# Redirect DNS to Adguard (localhost)
proxy-dnssec
server=127.0.0.1#5357
no-resolv
edns-packet-max=1232
# Prevent DNS leaks and block Bogus Private IP Responses
domain-needed
bogus-priv
# Prevent DNS rebinding attacks
stop-dns-rebind
# Prevent External Access to Local DNS
local-service
# Ensure Hostnames Resolve Properly
expand-hosts' | sudo tee /etc/NetworkManager/dnsmasq.d/00_dnsmasq-adguard.conf > /dev/null
Создайте файл конфигурации для общих интерфейсов, чтобы перенаправлять DNS-запросы в AdGuardHome и включить EDNS Client Subnet (ECS):
echo '# Redirect DNS to Adguard
proxy-dnssec
server=127.0.0.1#5357
no-resolv
# Enable EDNS Client Subnet (ECS) to pass client details
add-mac
add-subnet=32,128
edns-packet-max=1232
# Prevent DNS leaks and block Bogus Private IP Responses
domain-needed
bogus-priv
# Prevent DNS rebinding attacks
stop-dns-rebind
# Prevent External Access to Local DNS
local-service
# Ensure Hostnames Resolve Properly
expand-hosts' | sudo tee /etc/NetworkManager/dnsmasq-shared.d/00_dnsmasq-shared_adguard.conf > /dev/null
Настройте параметры DHCP для usb0 (Ethernet Gadget) и wlan0 (точка доступа Wi-Fi):
echo '########################################
# DHCP/DNS for usb0 -> ONlY ONE CLIENT #
########################################
# Assign static IP to WORKSTATION:
dhcp-host=WORKSTATION,192.168.77.77
# DHCP range:
dhcp-range=set:usb0,192.168.77.10,192.168.77.255,255.255.255.0,24h
# Default Gateway:
dhcp-option=tag:usb0,3,192.168.77.1
# DNS server:
dhcp-option=tag:usb0,6,192.168.77.1
# NTP server:
dhcp-option=tag:usb0,option:ntp-server,192.168.77.1
# Request hostnames:
dhcp-option=tag:usb0,12
############################################
# DHCP/DNS for wlan0 -> REQUEST HOSTNAMES #
############################################
# DHCP range:
dhcp-range=set:wlan0,192.168.37.10,192.168.37.250,255.255.255.0,24h
# Default Gateway:
dhcp-option=tag:wlan0,3,192.168.37.1
# DNS server:
dhcp-option=tag:wlan0,6,192.168.37.1
# NTP server:
dhcp-option=tag:wlan0,option:ntp-server,192.168.37.1
# Request hostnames:
dhcp-option=tag:wlan0,12' | sudo tee /etc/NetworkManager/dnsmasq-shared.d/01_usb0-wlan0.conf > /dev/null
ВАЖНО: Эти изменения вступят в силу только после перезапуска NetworkManager. Однако, поскольку вы подключены по SSH, перезапуск NetworkManager прервёт ваше соединение. Единственный способ применить эти изменения без потери доступа — полная перезагрузка системы.
⚠ НЕ перезагружайте Raspberry Pi на этом этапе!
AdGuardHome и Unbound ещё не настроены, и нет правил брандмауэра для обеспечения правильной маршрутизации сети. Перезагрузка сейчас может нарушить подключение. Продолжайте выполнение оставшихся шагов настройки перед перезапуском.**
Чтобы ваш Mac отображался как уникальный клиент в AdGuardHome, необходимо назначить ему статический IP-адрес (см. конфигурацию выше). Однако, так как на вашем Mac включена рандомизация MAC-адресов, его MAC-адрес не может служить надёжным идентификатором. Вместо этого мы зададим фиксированное имя хоста — WORKSTATION, что позволит стабильно назначать нужный статический IP. Откройте терминал на вашем Mac и выполните следующие команды для настройки имени хоста:
sudo scutil --set HostName WORKSTATION
sudo scutil --set LocalHostName WORKSTATION
sudo scutil --set ComputerName WORKSTATION
dscacheutil -flushcache
Когда включена рандомизация MAC-адресов, Dnsmasq может назначить другой IP-адрес после перезагрузки, так как видит новый MAC-адрес. Чтобы AdGuardHome стабильно распознавал WORKSTATION с правильным статическим IP, необходимо очищать файл /var/lib/NetworkManager/dnsmasq-usb0.leases перед запуском NetworkManager.
Войдите на свой Raspberry Pi под пользователем admin и подготовьте место для хранения скрипта:
[ -d ~/script ] || mkdir ~/script && [ -d ~/script/DNS ] || mkdir ~/script/DNS
Далее создайте скрипт очистки:
echo '#!/bin/bash
> /var/lib/NetworkManager/dnsmasq-usb0.leases' | sudo tee ~/script/DNS/clear-usb0-leases.sh > /dev/null
Сделайте скрипт исполняемым:
sudo chmod +x ~/script/DNS/clear-usb0-leases.sh
Создайте службу systemd, которая будет запускать этот скрипт перед стартом NetworkManager:
echo '[Unit]
Description=Clear dnsmasq leases for usb0
After=local-fs.target
Before=NetworkManager.service
[Service]
Type=oneshot
ExecStart=/home/admin/script/DNS/clear-usb0-leases.sh
[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/clear-dnsmasq-leases.service > /dev/null
Перезагрузите systemd и активируйте службу, чтобы она запускалась при каждом выключении:
sudo systemctl daemon-reload
sudo systemctl enable clear-dnsmasq-leases.service
Теперь при каждом запуске Raspberry Pi файл dnsmasq-usb0.leases будет очищаться перед тем, как NetworkManager начнёт работу. Это гарантирует, что dnsmasq назначит правильный статический IP вашему WORKSTATION, даже если рандомизация MAC включена.
⚠ ВАЖНО: Выполнение глав 13–19 шаг за шагом в правильном порядке критически важно! Любая ошибка в конфигурации может вызвать проблемы с DNS, что приведёт к потере доступа к интернету для вашего Raspberry Pi и подключённых к нему клиентов — или даже полностью заблокирует вас. Даже небольшие ошибки или пропущенные шаги могут привести к тому, что некоторые аспекты настройки не будут работать как ожидалось. Действуйте осторожно и следуйте каждому шагу точно.
Unbound — это валидирующий (DNSSEC) и рекурсивный DNS-сервер, который кэширует запросы для повышения эффективности. Позже мы настроим AdGuardHome так, чтобы он использовал Unbound в качестве единственного вышестоящего DNS-сервера. Основная проблема традиционных DNS-резолверов — это доверие. При использовании стороннего DNS-провайдера мы должны доверять тому, что он не записывает, не анализирует и не продаёт данные наших DNS-запросов. Развёртывая Unbound, мы устраняем эту зависимость и получаем следующие преимущества:
КОНФИДЕНЦИАЛЬНОСТЬ: Unbound выполняет полное рекурсивное разрешение, то есть начинает процесс поиска DNS с корневых серверов имён и следует по иерархии, пока не достигнет авторитетного сервера имён, ответственного за запрашиваемый домен. Это устраняет зависимость от централизованного DNS-посредника, который мог бы фиксировать или анализировать наши запросы.
СКОРОСТЬ: AdGuardHome уже включает встроенный кэш DNS, но в сочетании с расширенными функциями кэширования Unbound — такими как aggressive-nsec, prefetch и serve-expired — время отклика на запросы ещё больше сокращается, а общая производительность улучшается.
НЕДОСТАТОК: Отсутствие шифрования
Один из основных минусов отказа от DNS-посредника — отсутствие шифрования. Запросы к корневым серверам имён и авторитетным DNS-серверам отправляются в открытом виде по UDP/TCP на порт 53, что делает их уязвимыми для перехвата и анализа.
Чтобы снизить этот риск, можно зашифровать DNS-запросы с помощью DNS-over-TLS (DoT). Однако в описанной здесь настройке мы не будем использовать этот вариант, так как корневые серверы имён (пока) не поддерживают DoT или DoH (DNS-over-HTTPS).
Это означает, что если мы выбираем отказ от сторонних DNS-резолверов, то должны также отказаться от шифрования. В то же время DNSSEC (включённый в Unbound) всё же обеспечивает преимущества в области безопасности, гарантируя, что DNS-ответы являются аутентичными (поступают от легитимного DNS-сервера) и не изменены (обеспечивается целостность данных). Хотя это не шифрует запросы, но предотвращает DNS-спуфинг и атаки «человек посередине», проверяя легитимность ответов.
В итоге цепочка DNS-запросов будет работать так:
Dnsmasq: порт 53 → AdGuardHome: порт 5357 → Unbound: порт 7353:
+----------------------+ +----------------------+ +-------------------+
| User Device | DNS | NetworkManager DNS | DNS | AdGuardHome |
| (Any App or Browser) | -----> | dnsmasq: 53 | -----> | Filtering: 5357 |
+----------------------+ +----------------------+ +-------------------+
|
| DNS
v
+----------------------------+
| Unbound |
| Recursive Resolver: 7353 |
| - DNSSEC Validation |
| - Root-to-Auth Resolution |
| - Caching Enabled |
+----------------------------+
Это схема обработки DNS-запросов в Unbound — в этом примере клиент хочет посетить term7.info:
+-------------------+ +------------------------+
| | | |
| Client: Browser | ------------------->| https://term7.info |
| | | |
+-------------------+ +------------------------+
^
||
term7.info? || IP: 89.147.108.191
||
v
+------------------+ +------------+
| AdGuardHome | /------------>| Root |
| Filter + Cache | //------------ | Server |
+------------------+ .info? // +------------+
^ //
|| //
term7.info? || IP: 89.147.108.191 // .info!
|| //
v //
+-------------------+ ---------------//
| Unbound | <---------------/ term7.info? +--------------------------+
| | ------------------------------------>| TLD Server |
| Recursive Caching | <------------------------------------ | Top Level Domain: .info |
| Resolver DNSSEC | ---------------\ term7.info! +--------------------------+
+-------------------+ <---------------\\
\\
\\
\\ term7.info -> IP?
\\
IP: 89.147.108.191 \\
\\ +-------------------------------+
\\------------>| Authoritative Name Server |
\------------ | term7.info |
+-------------------------------+
sudo apt install -y unbound unbound-anchor
Наша конфигурация Unbound предназначена для рекурсивного DNS-резолвера с акцентом на конфиденциальность и высокую производительность, с поддержкой валидации DNSSEC, улучшенным кэшированием и усилением безопасности. Скачайте наш предварительно настроенный файл конфигурации Unbound из нашего репозитория:
sudo curl -L -o /etc/unbound/unbound.conf.d/unbound-dnssec.conf "https://codeberg.org/term7/Going-Dark/raw/branch/main/Pi%20Configuration%20Files/unbound/unbound-dnssec.conf"
Функции конфиденциальности и безопасности:
Улучшения производительности:
Теперь создадим второй файл конфигурации для определения локальных зон и включения обратных запросов для wlan0 и usb0, что позволит разрешать локальные имена хостов в нашей сети:
echo 'server:
# Serve static local websites:
local-zone: "adguard.home." static
local-data: "adguard.home. IN A 192.168.77.1"
#PTR Record for localhost
local-data-ptr: "127.0.0.1 localhost"
# Allow reverse lookups for wlan0 (192.168.37.x)
local-zone: "37.168.192.in-addr.arpa." transparent
local-data-ptr: "192.168.37.1 hotspot.local"
# Allow reverse lookups for usb0 (192.168.77.x)
local-zone: "77.168.192.in-addr.arpa." transparent
local-data-ptr: "192.168.77.1 usb0.local"
######### CUSTOM RULES TO REACH LAN NETWORK #########
# Use LAN DNS for private domain "lan."
# Adjust "lan" to your private lan domain
private-domain: "lan"
private-address: 192.168.0.0/16
domain-insecure: "lan."
# EXAMPLE: Local override for the router hostname
# Uncomment and adjust "router.lan" to match your setup
# local-zone: "lan." transparent
# local-data: "router.lan. IN A 192.168.1.1"
forward-zone:
name: "1.168.192.in-addr.arpa."
forward-addr: 192.168.1.1
#####################################################
# Allow Unbound to read hostnames from DHCP leases
auth-zone:
name: "37.168.192.in-addr.arpa."
zonefile: "/var/lib/unbound/unbound-wlan0.zone"
fallback-enabled: yes
auth-zone:
name: "77.168.192.in-addr.arpa."
zonefile: "/var/lib/unbound/unbound-usb0.zone"
fallback-enabled: yes' | sudo tee /etc/unbound/unbound.conf.d/local-zones.conf > /dev/null
Эта конфигурация особенно полезна по следующим причинам:
AdGuardHome сможет регистрировать имена хостов клиентов (если они предоставлены клиентом). Это позволяет видеть, какой клиент подключается к какому домену в журнале запросов.
Далее в этом руководстве мы настроим обратный прокси Nginx для обслуживания веб-интерфейса AdGuardHome. Наличие локального разрешения имен хостов гарантирует, что веб-интерфейс может надежно доступ через локальное доменное имя вместо IP-адреса.
Эта настройка не работает «из коробки» из-за двух ключевых проблем: Dnsmasq генерирует зонный файл, несовместимый с синтаксисом Unbound. Чтобы решить это, нам нужен скрипт, который преобразует файл аренды в формат, читаемый Unbound.
Кроме того, Dnsmasq должен запускать этот скрипт каждый раз, когда подключается новый клиент. Это обеспечивает автоматическое обновление зонного файла Unbound, сохраняя актуальность разрешения имен хостов.
Создайте скрипт, который преобразует файл аренды NetworkManager в формат, совместимый с Unbound:
sudo tee /home/admin/script/DNS/update-unbound-leases.sh > /dev/null << 'EOF'
#!/bin/bash
# Loop through each interface (wlan0 and usb0)
for iface in wlan0 usb0; do
# Define lease file and corresponding Unbound zone file paths for the interface
LEASE_FILE="/var/lib/NetworkManager/dnsmasq-${iface}.leases"
UNBOUND_ZONE_FILE="/var/lib/unbound/unbound-${iface}.zone"
# If the lease file doesn't exist or is empty, create a placeholder zone file
if [[ ! -s "$LEASE_FILE" ]]; then
echo "; Unbound generated zone file - No active leases found" > "$UNBOUND_ZONE_FILE"
continue
fi
# Initialize a new Unbound zone file with a header comment
echo "; Unbound generated zone file from dnsmasq leases" > "$UNBOUND_ZONE_FILE"
# Process each lease entry in the lease file
while read -r LEASE_TIME MAC_ADDR IP HOSTNAME CLIENTID; do
# Skip the entry if the IP address is missing
if [[ -z "$IP" ]]; then
continue
fi
# Set hostname to 'UNKNOWN' if it's missing or a placeholder '*'
if [[ -z "$HOSTNAME" || "$HOSTNAME" == "*" ]]; then
HOSTNAME="UNKNOWN"
fi
# Convert the IP address into PTR record format (reverse order)
PTR_IP=$(echo "$IP" | awk -F. '{print $4"."$3"."$2"."$1}')
# Append the PTR record to the Unbound zone file
echo "$PTR_IP.in-addr.arpa. 86400 IN PTR $HOSTNAME." >> "$UNBOUND_ZONE_FILE"
done < "$LEASE_FILE"
done
# Reload Unbound to apply the updated zone files
systemctl reload unbound
EOF
Сделайте этот скрипт исполняемым:
sudo chmod +x ~/script/DNS/update-unbound-leases.sh
Настройте Dnsmasq на автоматический запуск скрипта при подключении клиента:
echo "" | sudo tee -a /etc/NetworkManager/dnsmasq-shared.d/00_dnsmasq-shared_adguard.conf > /dev/null
echo "# Script to reconfigure Unbound zonefile for PTR requests" | sudo tee -a /etc/NetworkManager/dnsmasq-shared.d/00_dnsmasq-shared_adguard.conf > /dev/null
echo "dhcp-script=/home/admin/script/DNS/update-unbound-leases.sh" | sudo tee -a /etc/NetworkManager/dnsmasq-shared.d/00_dnsmasq-shared_adguard.conf > /dev/null
Чтобы все DNS-запросы направлялись через AdGuardHome и Unbound, нужно настроить NetworkManager на использование нашего локального резолвера:
sudo nmcli con modify Wi-Fi ipv4.dns 127.0.0.1
sudo nmcli con modify Ethernet ipv4.dns 127.0.0.1
Далее в этом руководстве мы настроим VPN WIREGUARD и ПРОЗРАЧНЫЙ ПРОКСИ TOR. Каждый из этих режимов требует динамических изменений в конфигурации DNS Unbound.
Однако в редких случаях — например, если ваш Raspberry Pi аварийно завершает работу или вы забыли корректно отключить WireGuard или Tor — система может перезагрузиться с некорректной конфигурацией Unbound. Это может привести к потере подключения к интернету при запуске.
Чтобы предотвратить это, мы создадим простой скрипт и сервис systemd, который будет автоматически восстанавливать стандартные настройки Unbound при каждой загрузке Raspberry Pi.
Создайте новый скрипт, который сбрасывает Unbound к стандартной конфигурации с поддержкой DNSSEC:
sudo tee /home/admin/script/DNS/restore-unbound-config.sh << 'EOF'
#!/bin/bash
# Config Files
UNBOUND_MAIN_CONFIG="/etc/unbound/unbound.conf.d/unbound-dnssec.conf"
UNBOUND_CONFIG="/etc/unbound/unbound.conf.d/local-zones.conf"
# Restore Unbound main configuration
sed -i 's/do-not-query-localhost: no/do-not-query-localhost: yes/' "$UNBOUND_MAIN_CONFIG"
sed -i 's/val-permissive-mode: yes/val-permissive-mode: no/' "$UNBOUND_MAIN_CONFIG"
# Remove TorProxy or WireGuard DNS Config and add fallback setting
sed -i '/fallback-enabled: yes/,$d' "$UNBOUND_CONFIG"
echo " fallback-enabled: yes" >> "$UNBOUND_CONFIG"
EOF
Сделайте скрипт исполняемым:
sudo chmod +x ~/script/DNS/restore-unbound-config.sh
Теперь создайте новый модуль сервиса для запуска скрипта перед стартом Unbound:
echo '[Unit]
Description=Restore Unbound configuration before Unbound starts
After=network.target
Before=unbound.service
[Service]
Type=oneshot
ExecStart=/home/admin/script/DNS/restore-unbound-config.sh
[Install]
WantedBy=multi-user.target' | sudo tee /etc/systemd/system/restore-unbound-config.service > /dev/null
Перезагрузите systemd и включите сервис, чтобы он запускался при каждой загрузке:
sudo systemctl daemon-reload
sudo systemctl enable restore-unbound-config.service
Отныне ваш Raspberry Pi будет автоматически восстанавливать корректную конфигурацию Unbound при запуске — обеспечивая подключение к интернету, даже если система ранее завершила работу неожиданно или с активным неправильным сетевым режимом.
⚠ ВАЖНО: Выполнение глав 13–19 шаг за шагом в правильном порядке критически важно! Любая ошибка в конфигурации может вызвать проблемы с DNS, что приведёт к потере доступа к интернету для вашего Raspberry Pi и подключённых к нему клиентов — или даже полностью заблокирует вас. Даже небольшие ошибки или пропущенные шаги могут привести к тому, что некоторые аспекты настройки не будут работать должным образом. Действуйте осторожно и точно следуйте каждому шагу.
Теперь мы установим AdGuardHome — мощный DNS-фильтр, который блокирует рекламу, трекинговые домены и вредоносные сайты. Он улучшает конфиденциальность и безопасность для всех подключённых устройств, блокируя нежелательный контент на уровне DNS.
Перед установкой AdGuardHome убедитесь, что каталог сборки существует, и перейдите в него:
[ -d ~/build ] || mkdir ~/build && cd ~/build
Выполните следующую команду, чтобы загрузить и извлечь последнюю версию AdGuardHome:
curl -sSL https://github.com/AdguardTeam/AdGuardHome/releases/latest/download/AdGuardHome_linux_arm64.tar.gz | tar -xz
Затем перейдите в извлечённый каталог и запустите установку:
cd AdGuardHome && sudo ./AdGuardHome -s install
Примечание: Настройку AdGuardHome мы выполним позже в руководстве. На этом этапе установка только подготавливает систему.
⚠ ВАЖНО: Выполнение глав 13–19 шаг за шагом в правильном порядке критически важно! Любая ошибка в конфигурации может вызвать проблемы с DNS, что приведёт к потере доступа к интернету для вашего Raspberry Pi и подключённых к нему клиентов — или даже полностью заблокирует вас. Даже небольшие ошибки или пропущенные шаги могут привести к тому, что некоторые аспекты настройки не будут работать должным образом. Действуйте осторожно и точно следуйте каждому шагу.
В предыдущих главах мы настроили встроенный в NetworkManager Dnsmasq, включили обратные запросы через Unbound и установили AdGuardHome. Теперь нужно настроить шифрование с помощью самоподписанного сертификата, который будет использоваться NGINX для обслуживания adguard.home по HTTPS.
Цель — получить доступ к веб-интерфейсу AdGuardHome по локальному адресу: https://adguard.home
Кроме того, этот сертификат позволит AdGuardHome поддерживать зашифрованные DNS-запросы через DNS-over-HTTPS (DoH) в качестве резервного метода наряду с нашей конфигурацией Unbound.
Выполните следующую команду, чтобы убедиться в наличии необходимых каталогов:
mkdir -p ~/tools/CA/SSL ~/script/SSL
Перейдите в каталог конфигурации Центра сертификации (CA):
cd ~/tools/CA
Создайте самоподписанный ключ и сертификат Центра сертификации (CA) (срок действия 10 лет, совместимый с Apple):
openssl req -x509 -new -nodes \
-newkey rsa:2048 \
-keyout term7-CA.key \
-out term7-CA.pem \
-days 3650 \
-subj "/CN=term7-CA" \
-addext "basicConstraints=critical,CA:true,pathlen:0" \
-addext "keyUsage=critical,keyCertSign,cRLSign"
Убедитесь, что файлы принадлежат пользователю root и имеют правильные права доступа:
sudo chown root:root term7-CA.key term7-CA.pem term7-CA.srl
sudo chmod 600 term7-CA.key
sudo chmod 644 term7-CA.pem term7-CA.srl
Перейдите в каталог конфигурации SSL:
cd ~/tools/CA/SSL
Создайте файл конфигурации OpenSSL для adguard.home:
echo '[ req ]
default_bits = 2048
default_md = sha256
prompt = no
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
CN = adguard.home
[ v3_req ]
subjectAltName = @alt_names
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ alt_names ]
DNS.1 = adguard.home
IP.1 = 192.168.77.1' | sudo tee /home/admin/tools/CA/SSL/openssl-adguardhome.cnf > /dev/null
Теперь сгенерируйте закрытый ключ для adguard.home:
openssl genrsa -out adguard.home.key 2048
Создайте запрос на подпись сертификата (CSR):
openssl req -new -key adguard.home.key -out adguard.home.csr -config openssl-adguardhome.cnf
Подпишите запрос на подпись сертификата (CSR) с помощью Локального центра сертификации (CA):
sudo openssl x509 -req -in adguard.home.csr -CA ../term7-CA.pem -CAkey ../term7-CA.key -CAcreateserial -out adguard.home.crt -days 90 -extensions v3_req -extfile openssl-adguardhome.cnf
Создайте сертификат с полной цепочкой:
cat adguard.home.crt ../term7-CA.pem > adguard.home-fullchain.crt
Скопируйте сертификат CA в каталог доверенных сертификатов системы:
sudo cp ~/tools/CA/term7-CA.pem /usr/local/share/ca-certificates/term7-CA.crt
Обновите хранилище сертификатов системы:
sudo update-ca-certificates
Поскольку мы применили строгий контроль доступа пользователей, вход от имени root запрещён. Чтобы передать сертификат на Mac, сначала скопируем его в учётную запись обычного пользователя:
sudo cp ~/tools/CA/term7-CA.pem /home/term7/
Теперь на вашем Mac откройте новое окно терминала и выполните следующую команду, чтобы безопасно скопировать сертификат в папку «Загрузки». После завершения передачи сразу удалите его из учётной записи обычного пользователя Raspberry Pi:
scp -P 8519 term7@192.168.77.1:term7-CA.pem ~/Downloads/ && ssh -p 8519 term7@192.168.77.1 "rm term7-CA.pem"
Выполните следующую команду, чтобы добавить сертификат в системное хранилище ключей macOS и отметить его как доверенный для всех пользователей:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ~/Downloads/term7-CA.pem
Это гарантирует, что сертификат будет распознаваться как корневой центр сертификации, что позволит вам получить доступ к https://adguard.home без предупреждений о безопасности.
Если вы когда-нибудь захотите удалить этот сертификат, выполните:
sudo security delete-certificate -c "term7-CA" /Library/Keychains/System.keychain
Создайте скрипт обновления (он будет запускаться только если срок действия сертификата истекает в течение 30 дней):
sudo tee /home/admin/script/SSL/renew-cert.sh > /dev/null <<'EOF'
#!/bin/bash
set -euo pipefail
umask 077
# Where to store the log (overwrite on each run)
LOG_FILE="/home/admin/script/SSL/renewal.log"
mkdir -p "$(dirname "$LOG_FILE")"
: > "$LOG_FILE"
# ----- Timestamp every log line -----
if command -v ts >/dev/null 2>&1; then
exec > >(ts "[%Y-%m-%d %H:%M:%S]" >> "$LOG_FILE") 2>&1
else
exec > >(awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0; fflush(); }' >> "$LOG_FILE") 2>&1
fi
# ----- Config -----
CA_DIR="/home/admin/tools/CA"
SSL_DIR="$CA_DIR/SSL"
CA_CERT="$CA_DIR/term7-CA.pem"
CA_KEY="$CA_DIR/term7-CA.key"
CA_SERIAL="$CA_DIR/term7-CA.srl"
DAYS=825
DOMAINS=("adguard.home")
RESTART_SERVICES=("nginx" "AdGuardHome")
# --- Renewal loop ---
for DOMAIN in "${DOMAINS[@]}"; do
CNF_FILE="$SSL_DIR/openssl-${DOMAIN//./}.cnf"
CRT_FILE="$SSL_DIR/$DOMAIN.crt"
KEY_FILE="$SSL_DIR/$DOMAIN.key"
CSR_FILE="$SSL_DIR/$DOMAIN.csr"
FULLCHAIN="$SSL_DIR/$DOMAIN-fullchain.crt"
if [ ! -f "$CRT_FILE" ]; then
DAYS_LEFT=0
else
ENDLINE="$(openssl x509 -enddate -noout -in "$CRT_FILE" 2>/dev/null || true)"
if [[ "$ENDLINE" =~ ^notAfter= ]]; then
EXPIRY_RAW="${ENDLINE#notAfter=}"
EXPIRY_EPOCH=$(date -d "$EXPIRY_RAW" +%s)
NOW_EPOCH=$(date +%s)
SECS_LEFT=$(( EXPIRY_EPOCH - NOW_EPOCH ))
DAYS_LEFT=$(( SECS_LEFT > 0 ? SECS_LEFT / 86400 : 0 ))
else
DAYS_LEFT=0
fi
fi
if [ "$DAYS_LEFT" -gt 30 ]; then
echo "$DOMAIN: certificate expiring in $DAYS_LEFT days — not renewing."
continue
else
echo "$DOMAIN: certificate expiring in $DAYS_LEFT days — renewing..."
fi
openssl req -new -key "$KEY_FILE" -out "$CSR_FILE" -config "$CNF_FILE"
openssl x509 -req \
-in "$CSR_FILE" \
-CA "$CA_CERT" -CAkey "$CA_KEY" \
-CAserial "$CA_SERIAL" -CAcreateserial \
-out "$CRT_FILE" \
-days "$DAYS" \
-extensions v3_req -extfile "$CNF_FILE"
cat "$CRT_FILE" "$CA_CERT" > "$FULLCHAIN"
NEW_END="$(openssl x509 -in "$CRT_FILE" -noout -enddate | sed 's/^notAfter=//')"
echo "$DOMAIN: new certificate expires on $NEW_END"
done
# --- Restart services ---
for svc in "${RESTART_SERVICES[@]}"; do
if systemctl is-enabled "$svc" >/dev/null 2>&1 || systemctl is-active "$svc" >/dev/null 2>&1; then
sudo systemctl restart "$svc"
fi
done
EOF
Сделайте скрипт исполняемым:
sudo chmod +x /home/admin/script/SSL/renew-cert.sh
В конце создайте задачу cron, которая запускает скрипт при каждой перезагрузке:
( sudo crontab -l 2>/dev/null | grep -v 'renew-cert.sh' ; \
echo '@reboot /home/admin/script/SSL/renew-cert.sh' \
) | sudo crontab -
⚠ ВАЖНО: Выполнение глав 13–19 шаг за шагом в правильном порядке критически важно! Любая ошибка в конфигурации может вызвать проблемы с DNS, что приведёт к потере доступа к интернету для вашего Raspberry Pi и подключённых к нему клиентов — или даже полностью заблокирует вас. Даже небольшие ошибки или пропущенные шаги могут привести к тому, что некоторые аспекты настройки не будут работать как ожидается. Действуйте осторожно и точно следуйте каждому шагу.
В этом разделе мы настроим NGINX как обратный прокси для веб-интерфейса AdGuardHome. Это позволит нам безопасно предоставлять интерфейс, а также добавить дополнительные опции кастомизации.
Сначала установите NGINX — современный и лёгкий веб-сервер:
sudo apt install -y nginx
По умолчанию NGINX настроен на прослушивание IPv6, но ранее мы отключили IPv6 на этой системе, поэтому служба nginx.service не сможет запуститься. Чтобы предотвратить это, нужно изменить файл конфигурации по умолчанию и отключить поддержку IPv6:
sudo sed -i 's/^\(\s*listen \[::\]:80 default_server;\)/# \1/' /etc/nginx/sites-available/default
Теперь настроим NGINX для работы в качестве обратного прокси для веб-интерфейса AdGuardHome, а также для передачи запросов DNS-over-HTTPS (DoH) между подключёнными клиентами и AdGuardHome.
Выполните следующую команду, чтобы создать конфигурацию:
echo 'server {
listen 192.168.77.1:443 ssl http2;
server_name adguard.home;
ssl_certificate /home/admin/tools/CA/SSL/adguard.home.crt;
ssl_certificate_key /home/admin/tools/CA/SSL/adguard.home.key;
# Proxy AdGuardHome Web Interface
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Proxy DNS-over-HTTPS (DoH) Requests to AdGuardHome
location /dns-query {
proxy_pass https://127.0.0.1:7443/dns-query$is_args$args;
proxy_ssl_server_name on;
proxy_ssl_verify off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Preserve query strings
proxy_redirect off;
}
}
server {
listen 192.168.77.1:80;
server_name adguard.home;
# Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
}' | sudo tee /etc/nginx/sites-available/nginx-adguard > /dev/null
Чтобы активировать созданную конфигурацию NGINX:
sudo ln -s /etc/nginx/sites-available/nginx-adguard /etc/nginx/sites-enabled/
Перед перезапуском NGINX проверьте конфигурацию на наличие синтаксических ошибок:
sudo nginx -t
Если проверка прошла успешно, перезапустите NGINX:
sudo systemctl restart nginx
Чтобы разрешить локальное разрешение имени adguard.home, выполните эту команду на вашем Mac и на Raspberry Pi:
grep -q '192\.168\.77\.1[[:space:]]\+adguard\.home' /etc/hosts || echo '192.168.77.1 adguard.home' | sudo tee -a /etc/hosts > /dev/null
⚠️ ВАЖНО: На этом этапе необходимые службы настроены, но брандмауэр ещё не настроен. Без правил брандмауэра маршрутизация не будет работать как ожидается, и ваша настройка может не функционировать корректно. Следующий раздел проведёт вас через настройку брандмауэра. Завершите этот раздел перед перезагрузкой Raspberry Pi.
⚠ ВАЖНО: Выполнение глав 13–19 шаг за шагом в правильном порядке критически важно! Любая ошибка в конфигурации может вызвать проблемы с DNS, что приведёт к потере доступа к интернету для вашего Raspberry Pi и подключённых к нему клиентов — или даже полностью заблокирует вас. Даже небольшие ошибки или пропущенные шаги могут привести к тому, что некоторые аспекты настройки не будут работать как ожидается. Действуйте осторожно и точно следуйте каждому шагу.
В этом разделе мы настроим nftables — современное приложение брандмауэра, которое установлено по умолчанию на вашем Raspberry Pi. Наше решение для брандмауэра разработано для максимальной безопасности, предотвращения несанкционированного доступа и обеспечения корректной работы только необходимых служб, защищая при этом подключённые устройства.
Чтобы избежать ошибок при ручной настройке, загрузите предварительно настроенную конфигурацию брандмауэра из репозитория:
sudo curl -L -o /etc/nftables.conf "https://codeberg.org/term7/Going-Dark/raw/branch/main/Pi%20 Configuration%20Files/nftables/nftables.conf"
Наш брандмауэр включает несколько механизмов безопасности для блокировки атак, обеспечения сегментации сети и предотвращения несанкционированного доступа:
⚠️ ВАЖНО: Настройте межсетевой экран для вашего Wi-Fi-адаптера: Если вы используете адаптер, отличный от ALFA AWUS036ACM, межсетевой экран перестанет работать! Выполните следующие команды, чтобы обновить конфигурацию межсетевого экрана с предсказуемым именем интерфейса вашего адаптера:
WIFI='PREDICTABLE-INTERFACE-NAME'
sudo sed -i "s/\bwlx00c0caae6319\b/$WIFI/" /etc/nftables.conf
⚠ Замените PREDICTABLE-INTERFACE-NAME на фактическое имя вашего Wi-Fi-адаптера. Для получения инструкций обратитесь к разделу 03 - ПРЕДВАРИТЕЛЬНЫЕ ТРЕБОВАНИЯ и 11 НАСТРОЙКА БЕСПРОВОДНОЙ ТОЧКИ ДОСТУПА.
Включите nftables, чтобы правила межсетевого экрана сохранялись после перезагрузки:
sudo systemctl enable nftables
⚠️ ВАЖНО: Предотвратите перезапись правил межсетевого экрана NetworkManager!
По умолчанию NetworkManager может вмешиваться в настройки межсетевого экрана. Наша настройка слишком сложна, чтобы допускать это:
sudo sed -i '/^dhcp=dnsmasq$/a firewall-backend=none' /etc/NetworkManager/NetworkManager.conf
Перезагрузите систему, чтобы применить все изменения:
sudo reboot now
Fail2ban следит за файлами журналов на предмет подозрительной активности (например, неудачные попытки входа по SSH) и реагирует, блокируя IP-адреса нарушителей с помощью правил межсетевого экрана. В нашей настройке SSH настроен на прослушивание порта 6666. Поскольку наша конфигурация nftables использует таблицу inet global, нам нужно создать выделенный набор Fail2ban и цепочку внутри этой таблицы.
sudo sed -i '/table inet global {/a\
\
# Create the Fail2ban set\
set f2b-sshd {\
type ipv4_addr\
flags timeout\
}\
\
# Create the Fail2ban chain that drops packets from IPs in the set\
chain f2b-sshd {\
ip saddr @f2b-sshd drop\
}' /etc/nftables.conf
Далее подключите новую цепочку f2b-sshd к существующей цепочке inbound:
sudo sed -i '/^[[:space:]]*chain inbound {$/{
n
s/\(policy drop;\)/\1\
\
# Check for banned IPs via Fail2ban\
jump f2b-sshd/
}' /etc/nftables.conf
Установите fail2ban:
sudo apt install -y fail2ban
Создайте пользовательское действие Fail2ban для nftables:
echo '[Definition]
actionstart =
actionstop =
# When banning an IP, add it to the set with the given bantime.
actionban = /usr/sbin/nft add element inet global f2b-sshd \{ <ip> timeout <bantime>s \}
# When unbanning an IP, remove it from the set.
actionunban = /usr/sbin/nft delete element inet global f2b-sshd \{ <ip> \}' | sudo tee /etc/fail2ban/action.d/nftables-ssh.conf > /dev/null
Далее нужно настроить fail2ban для мониторинга SSH на порту 6666 с использованием systemd journal, который является стандартным механизмом ведения журналов на Raspberry Pi:
echo '[sshd]
enabled = true
port = 6666
filter = sshd
backend = systemd
findtime = 600
maxretry = 2
bantime = 165600
ignoreip = 192.168.77.77
action = nftables-ssh[name=sshd, port=6666, protocol=tcp]' | sudo tee /etc/fail2ban/jail.local > /dev/null
Эта конфигурация следит за SSH на порту 6666, и если IP-адрес дважды не проходит аутентификацию, он будет заблокирован на 46 часов путем добавления правила в nftables для отбрасывания его пакетов. Единственный IP-адрес, освобожденный от этой политики, — это 192.168.77.77, который принадлежит нашей РАБОЧЕЙ СТАНЦИИ, подключенной через интерфейс usb0.
Перезагрузите межсетевой экран:
sudo nft -f /etc/nftables.conf
Перезапустите fail2ban:
sudo systemctl restart fail2ban
Проверьте статус Fail2ban:
sudo fail2ban-client status sshd
Используйте следующую команду, чтобы вывести список заблокированных IP-адресов в наборе fail2ban:
sudo nft list set inet global f2b-sshd
⚠ ВАЖНО: Выполнение глав 13–19 шаг за шагом в правильном порядке имеет решающее значение! Любая ошибка в конфигурации может вызвать проблемы с DNS, что приведет к потере подключения к интернету для вашего Raspberry Pi и подключенных к нему клиентов — или даже полностью заблокирует вас. Даже небольшие ошибки или пропущенные шаги могут привести к тому, что некоторые аспекты настройки не будут работать должным образом. Действуйте осторожно и точно следуйте каждому шагу.
Этот репозиторий предоставляет предварительно настроенную конфигурацию AdGuardHome, которую мы настоятельно рекомендуем использовать. Она специально адаптирована для предотвращения распространенных конфликтов, таких как пересечение портов с NGINX для HTTPS. Кроме того, она обеспечивает бесшовную интеграцию с нашей настройкой, а именно:
Кроме того, эта конфигурация включает:
- Заранее определённые резервные DNS-серверы для зашифрованных запросов (DNS-over-HTTPS), которые, по нашему мнению, вероятно, заслуживают доверия:
- https://doh.mullvad.net/dns-query
- https://dns.digitale-gesellschaft.ch/dns-query
- https://anycast.uncensoreddns.org/dns-query
- https://unicast.uncensoreddns.org/dns-query
- https://doh.libredns.gr/dns-query
- https://odvr.nic.cz/dns-query
- https://doh.ffmuc.net/dns-query
- Оптимизированные настройки кэширования для улучшения производительности.
- Всесторонние опции ведения журнала и отладки.
- Несколько DNS-фильтров для блокировки рекламы, трекеров и вредоносных доменов.
Используя эту настройку, вы можете избежать потенциальных проблем и обеспечить плавное развёртывание без лишних хлопот. Если вы не знаете точно, что делаете, мы рекомендуем не изменять наши Настройки шифрования и не использовать встроенный DHCP-сервер AdGuardHome. Мы настроили NetworkManager и Dnsmasq для обработки DHCP.
Перед применением новой конфигурации остановите службу AdGuardHome:
sudo systemctl stop AdGuardHome
Получите заранее настроенную конфигурацию из репозитория:
sudo curl -L -o /home/admin/build/AdGuardHome/AdGuardHome.yaml "https://codeberg.org/term7/Going-Dark/raw/branch/main/Pi%20Configuration%20Files/adguard-home/AdGuardHome.yaml"
Ограничьте права доступа к файлу для повышения безопасности:
sudo chmod 600 ~/build/AdGuardHome/AdGuardHome.yaml
Поскольку это публичный репозиторий, пароль по умолчанию установлен как "default". Вы должны его изменить!
Чтобы сгенерировать хэшированный пароль bcrypt, установите пакет whois:
sudo apt install -y whois
Выполните следующие команды, чтобы заменить пароль по умолчанию:
PASSWORD='YOUR-NEW-PASSWORD'
sudo sed -i "s/^ password: default/ password: \"$(mkpasswd -m bcrypt "$PASSWORD")\"/" ~/build/AdGuardHome/AdGuardHome.yaml
⚠ Замените YOUR-NEW-PASSWORD на надёжный пароль по вашему выбору. Рассмотрите возможность использования менеджера паролей для генерации безопасного пароля.
После обновления пароля перезапустите службу:
sudo systemctl start AdGuardHome
Теперь проверьте свою настройку:
ПОЗДРАВЛЯЕМ
Ваша установка AdGuardHome теперь полностью настроена и работает!
Чтобы проверить, работает ли валидация DNSSEC, посетите этот сайт:
https://wander.science/projects/dns/dnssec-resolver-test/
В этом разделе мы кратко рассмотрим блокировочные и разрешённые списки DNS — два важных инструмента для управления DNS-трафиком в AdGuardHome.
AdGuardHome поддерживает список заблокированных доменов, которые будут явно заблокированы. По умолчанию в него входит только version.bind, но мы расширили этот список, чтобы охватить домены, обычно используемые для диагностики DNS, отладки или тестирования сети, а не для обычного просмотра веб-страниц или использования приложений. Блокировка этих доменов помогает усилить конфиденциальность, предотвращая утечку информации об IP и сервере, уменьшает ненужные DNS-запросы и предотвращает раскрытие внутренних деталей DNS:
version.bindid.serverhostname.binddevices.resolving.planetlab.google.comwhoami.ultradns.netwhoami.akamai.netdebug.opendns.comresolver.dnscrypt.infoedns-client-subnet.test-ipv6.comtest.dnssec-or-not.netporttest.dns-oarc.netВ этом разделе мы явно разрешаем домен check.torproject.org:
! Allow Tor Check
!
@@||torproject.org^$important
Этот домен используется позже в нашей настройке ПРОЗРАЧНЫЙ ПРОКСИ TOR, чтобы проверить маршрутизацию через Tor. Поскольку он блокируется одним из наших заранее настроенных блокировочных списков, мы добавляем его в белый список здесь, чтобы обеспечить его корректную работу. Вы можете добавить свои собственные пользовательские правила разрешения или блокировки в этом разделе в зависимости от вашего конкретного случая использования.
Наши блокировочные списки по умолчанию взяты из этого отличного репозитория GitHub, который поддерживает Герд Хагези: https://github.com/hagezi/dns-blocklists
Следующие списки включены по умолчанию в нашей конфигурации:
1.
Hagezi: Потоки данных угроз
Описание: Значительно повышает безопасность! Блокирует вредоносное ПО, криптоджекинг, спам, мошенничество и фишинг.
Количество записей: 962584 / 21 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/tif.txt
2.
Hagezi: Multi ULTIMATE
Описание: Ultimate Sweeper — строго очищает интернет и защищает вашу конфиденциальность! Блокирует рекламу, партнёрские программы, трекинг, метрики, телеметрию, фишинг, вредоносное ПО, мошенничество, бесплатные хостинги, фейковые сайты, криптоджекинг и другой «мусор».
Количество записей: 334037 / 21 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/ultimate.txt
3.
Hagezi: Список блокировки DNS для азартных игр
Описание: Блокирует контент, связанный с азартными играми.
Количество записей: 704324 / 21 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/gambling.txt
4.
Hagezi: Список блокировки DNS для фейковых сайтов
Описание: Защищает от интернет-мошенничества, ловушек и подделок! Блокирует фейковые магазины, стриминговые платформы, подделки, платные ловушки и прочее.
Количество записей: 10744 / 20 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/fake.txt
5.
Hagezi: Список блокировки DNS для всплывающих реклам
Описание: Блокирует назойливые и вредоносные всплывающие рекламные окна.
Количество записей: 100339 / 20 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/popupads.txt
6.
Hagezi: Обход DoH/VPN/TOR/Proxy
Описание: Предотвращает попытки обхода вашего DNS, блокирует зашифрованный DNS, VPN, TOR, прокси.
Количество записей: 3888 / 20 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/doh-vpn-proxy-bypass.txt
7.
Hagezi: Список блокировки DNS для трекеров Amazon
Описание: Блокирует встроенные трекеры Amazon, которые отслеживают вашу активность.
Количество записей: 334 / 8 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/native.amazon.txt
8.
Hagezi: Список блокировки DNS для трекеров Windows/Office
Описание: Блокирует встроенные трекеры Windows/Office, которые отслеживают вашу активность.
Количество записей: 357 / 14 марта 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/native.winoffice.txt
9.
Hagezi: Список блокировки DNS для трекеров Apple
Описание: Блокирует встроенные трекеры Apple, которые отслеживают вашу активность.
Количество записей: 93 / 22 февраля 2025
https://codeberg.org/hagezi/mirror2/raw/branch/main/dns-blocklists/adblock/native.apple.txt
Этот список блокировки отключён по умолчанию и предназначен для опытных пользователей, которые хотят полностью ограничить онлайн-сервисы Apple. Это агрессивный список, блокирующий все известные домены Apple, а также множество сторонних сервисов, используемых инфраструктурой Apple.
⚠️ Предупреждение: включение этого списка полностью нарушит работу большинства сервисов Apple, включая (но не ограничиваясь): iCloud, Apple TV+, Apple Music, Apple Arcade, Apple Maps, Apple News+, Apple Pay, App Store, iMessage, FaceTime, FindMy и др.
Несмотря на широкий охват блокировки, мы активно поддерживаем минимальный список разрешённых доменов, необходимых для критических обновлений программного обеспечения и безопасности macOS.
10.
Term7: Полный список блокировки Apple
Описание: Полный список блокировки Apple — ВНИМАНИЕ: нарушает работу сервисов Apple
Комментарий: Разрешает критически важные обновления ПО и безопасности
Количество записей: 37 / 21 марта 2025
https://codeberg.org/term7/Break-Apple-Blocklist/raw/branch/main/Break-Apple-Blocklist.txt
В этом разделе мы настроим Raspberry Pi в качестве клиента WireGuard, который можно активировать при необходимости. Эта настройка беспрепятственно работает с AdGuardHome, который будет продолжать фильтровать рекламу и блокировать вредоносные домены перед тем, как DNS-запросы будут передаваться через туннель WireGuard VPN.
В нашей личной настройке мы установили сервер WireGuard на домашний маршрутизатор (с прошивкой OpenWRT). Когда мы путешествуем — будь то отель, аэропорт или работа из зарубежного кафе — наш Raspberry Pi передаёт весь сетевой трафик через защищённое, зашифрованное соединение WireGuard обратно на домашний маршрутизатор.
Это означает, что наш интернет-трафик защищён от локальных сетей и посторонних наблюдателей. Мы можем безопасно получать доступ к домашней сети и сервисам из любой точки мира, а устройства, подключённые к Raspberry Pi, будут выглядеть так, будто выходят в интернет с домашнего IP-адреса.
Вот как подключённое устройство будет выходить в интернет через наш WireGuard VPN:
+---------------------+ +-------------------------------+ +-----------------------+
| | | RASPBERRY PI | | |
| | | | | |
| Laptop / Phone | TCP | WIREGUARD CLIENT | encrypted TCP | WIREGUARD SERVER |
| NO VPN | <---> | 10.13.0.1 | <-------------> | --> Home Router |
| | DNS | | encrypted DNS | |
| | | Firewall | | |
+---------------------+ +-------------------------------+ +-----------------------+
^ ^
| |
DNS | TCP | DNS
| |
v v
+-------------------------------+ +--------------+
| | | |
| AdGuardHome --> Unbound | | INTERNET |
| DNS Filtering + Forwarding | | |
| | +--------------+
+-------------------------------+
Примечание: Полное руководство по настройке сервера WireGuard на домашнем маршрутизаторе выходит за рамки этого туториала.
В этом руководстве мы предполагаем, что:
Этот сервер может быть:
Если вы не используете собственный сервер, то Mullvad и ProtonVPN — надёжные варианты с акцентом на конфиденциальность. Они поддерживают WireGuard и позволяют скачивать конфигурационные файлы, которые работают без их приложений.
Примечание: Оба заявляют о строгой политике отсутствия логов, но, как и в случае с любыми VPN-провайдерами, это доверие невозможно независимо проверить. Если вы используете коммерческий VPN, в конечном итоге вам придётся доверять провайдеру.
В этом руководстве мы будем использовать файл конфигурации WireGuard с именем term7.wireguard.conf. Замените это имя на своё, где бы оно ни встречалось.
Поскольку мы отключили вход от имени root, нужно скопировать файл конфигурации в учётную запись не-root пользователя на Raspberry Pi. На Mac откройте терминал и выполните:
scp -P 6666 ~/Desktop/wireguard-export/term7.wireguard.conf term7@192.168.77.1:/home/term7/
Теперь войдите в систему на Raspberry Pi под своей учётной записью администратора и подготовьте каталог для хранения файла конфигурации:
[ -d ~/tools ] || mkdir ~/tools && [ -d ~/tools/wireguard-export ] || mkdir ~/tools/wireguard-export
Переместите файл конфигурации в новое расположение:
sudo mv /home/term7/term7.wireguard.conf ~/tools/wireguard-export/term7.wireguard.conf
NetworkManager имеет встроенную поддержку WireGuard. Мы используем её для импорта конфигурации:
sudo nmcli connection import type wireguard file ~/tools/wireguard-export/term7.wireguard.conf
После импорта рекомендуется сразу отключить соединение (на случай, если оно подключилось автоматически):
sudo nmcli con down term7.wireguard
Отключите автоподключение для этого VPN-профиля (мы будем активировать его вручную):
sudo nmcli con modify term7.wireguard connection.autoconnect no
Если у вас установлен WireGuard на домашнем маршрутизаторе и вы хотите иметь возможность доступа к веб-интерфейсу конфигурации и сервисам через браузер по VPN, добавьте необходимые маршруты для доступа к локальной сети (предполагаем, что веб-интерфейс маршрутизатора — 192.168.1.1):
sudo nmcli connection modify "term7.wireguard" +ipv4.routes "192.168.1.0/24"
Также установите рекомендуемое значение MTU:
sudo nmcli connection modify "term7.wireguard" wireguard.mtu 1380
Когда WireGuard активен, мы хотим настроить межсетевой экран так, чтобы трафик направлялся через VPN (term7.wireguard) вместо стандартного интерфейса Ethernet или Wi-Fi.
Сначала создайте необходимую структуру каталогов для конфигураций межсетевого экрана:
[ -d ~/script ] || mkdir ~/script && [ -d ~/script/nftables ] || mkdir ~/script/nftables
Создайте резервную копию стандартной конфигурации nftables:
sudo cp /etc/nftables.conf ~/script/nftables/nftables.conf
Скопируйте стандартные правила в качестве основы для конфигурации, специфичной для WireGuard:
sudo cp ~/script/nftables/nftables.conf ~/script/nftables/wireguard.conf
Обновите определение интерфейса в новой конфигурации, чтобы трафик направлялся через интерфейс WireGuard:
sudo sed -i '/DEV_WORLD = {/c\define DEV_WORLD = { term7.wireguard }' ~/script/nftables/wireguard.conf
Добавьте этот раздел в межсетевой экран, чтобы гарантировать, что TCP-сессии никогда не пытаются отправить пакеты, слишком большие для туннеля. Это происходит автоматически на уровне межсетевого экрана, поэтому вам не нужно вручную настраивать параметры MTU на клиентах:
sed -i '/^# ----- IPv6: drop all traffic -----/i \
# ----- MSS clamp for usb0/wlan0 -> WireGuard (avoid PMTU blackholes) -----\
table inet mangle {\
chain fwd_mss {\
type filter hook forward priority mangle; policy accept;\
\
# Clamp SYN MSS to 1340 when forwarding from private LAN to WireGuard\
iifname { usb0, wlan0 } oifname $DEV_WORLD tcp flags syn tcp option maxseg size set 1340\
}\
}\
' ~/script/nftables/wireguard.conf
Мы будем использовать скрипт NetworkManager, чтобы автоматически переключать конфигурации межсетевого экрана и стандартные настройки Unbound DNS при подключении или отключении WireGuard. Когда VPN активен, Unbound переходит в «режим VPN»: вместо выполнения рекурсивного разрешения DNS с использованием корневых серверов он теперь пересылает все DNS-запросы через зашифрованный туннель WireGuard. Эти пересланные запросы затем разрешаются на другой стороне туннеля. В нашем случае это наш домашний маршрутизатор, который настроен на использование DNS-over-HTTPS (DoH) для безопасного и конфиденциального разрешения DNS. Несмотря на переход к схеме пересылки, Unbound всё равно будет обеспечивать проверку DNSSEC, гарантируя, что DNS-ответы аутентифицированы и не были подделаны. Кроме того, скрипт перезапускает fail2ban, чтобы восстановить ранее заблокированные IP-адреса.
Создайте скрипт:
sudo tee /etc/NetworkManager/dispatcher.d/wireguard-handler > /dev/null << 'EOF'
#!/bin/bash
# Define Interfaces
WG_INTERFACE="term7.wireguard"
# Define Config Files
WG_RULES="/home/admin/script/nftables/wireguard.conf"
DEFAULT_RULES="/etc/nftables.conf"
UNBOUND_CONFIG="/etc/unbound/unbound.conf.d/local-zones.conf"
# Define WireGuard DNS Config
WG_DNS_CONFIG="# Upstream DNS via WireGuard\nforward-zone:\n name: \".\"\n forward-addr: 10.13.0.1"
case "$1" in
$WG_INTERFACE)
case "$2" in
up)
# Apply WireGuard firewall rules
/usr/sbin/nft -f "$WG_RULES"
# Append WireGuard DNS to Unbound if not already present
if ! grep -Fxq "$WG_DNS_CONFIG" "$UNBOUND_CONFIG"; then
echo -e "\n$WG_DNS_CONFIG" | sudo tee -a "$UNBOUND_CONFIG" > /dev/null
fi
sudo systemctl restart unbound
sudo systemctl restart fail2ban
;;
down)
# Restore default nftables rules
/usr/sbin/nft -f "$DEFAULT_RULES"
# Remove WireGuard DNS Config
sed -i '/fallback-enabled: yes/,$d' "$UNBOUND_CONFIG"
echo " fallback-enabled: yes" | sudo tee -a "$UNBOUND_CONFIG" > /dev/null
sudo systemctl restart unbound
sudo systemctl restart fail2ban
;;
esac
;;
esac
EOF
Сделайте скрипт исполняемым:
sudo chmod +x /etc/NetworkManager/dispatcher.d/wireguard-handler
Чтобы запустить WireGuard VPN:
sudo nmcli con up term7.wireguard
Чтобы остановить WireGuard VPN:
sudo nmcli con down term7.wireguard
Чтобы убедиться, что проверка DNSSEC всё ещё работает корректно, посетите:
https://wander.science/projects/dns/dnssec-resolver-test/
Чтобы проверить утечки DNS, используйте:
https://dnsleaktest.com
Единственный видимый IP-адрес должен принадлежать вашему VPN-провайдеру или DNS-серверу, настроенному на вашем домашнем маршрутизаторе или VPS. Если вы видите DNS-серверы вашего локального интернет-провайдера, туннель VPN или пересылка Unbound могут работать некорректно.
Наконец, мы установим Tor и настроим наш Raspberry Pi для работы в качестве прозрачного прокси Tor. Эта настройка может активироваться или деактивироваться вручную по мере необходимости. При активации весь трафик от подключённых устройств будет по-прежнему фильтроваться через AdGuardHome перед безопасной маршрутизацией через сеть Tor.
⚠️ ПРЕДУПРЕЖДЕНИЕ: Прозрачный прокси Tor — не рекомендуемый способ использования сети Tor. Если ваша цель — просто анонимный просмотр интернета, мы настоятельно рекомендуем использовать Tor Browser! Tor Browser специально разработан для обеспечения конфиденциальности и анонимности. Он стандартизирует поведение браузера, чтобы минимизировать отпечатки, и включает встроенную защиту от отслеживания, наблюдения через скрипты и утечек DNS. В отличие от этого, прозрачный прокси только перенаправляет сетевой трафик через сеть Tor. Он не предотвращает утечку идентифицирующей информации из приложений или браузеров. Использование обычного браузера через прозрачный прокси Tor почти наверняка всё равно раскроет уникальный отпечаток, подрывая основные преимущества использования Tor. Тем не менее, вы можете объединить прозрачный прокси Tor (для анонимизации всего системного трафика) с Tor Browser (для безопасного анонимного просмотра), чтобы извлечь выгоду из обеих функций: системной маршрутизации и защищённого браузера.
Тем не менее, правильно настроенный прозрачный прокси Tor может стать мощным инструментом для анонимизации общего трафика, защиты небраузерных приложений и создания среды, ориентированной на конфиденциальность. При правильной настройке с жёсткими правилами межсетевого экрана, защитой от утечек DNS и контролируемым сетевым доступом он позволяет создать надёжную «точку доступа конфиденциальности» типа «включил и работает» — идеальную для путешествий, общих сетей или защиты устройств без графического интерфейса. Именно этого мы и добиваемся в этом руководстве.
Вот как подключённое устройство будет выходить в интернет через наш прозрачный прокси Tor:
+---------------------+ +-------------------------------+ +----------------------+
| | | RASPBERRY PI | | |
| | | | | TOR ENTRY NODE |
| Laptop / Phone | TCP | TOR TRANSPARENT PROXY | encrypted TCP | |
| (No Tor Installed) | <---> | 10.192.0.1 / TransPort 9040 | <-------------> | KNOWS your real IP |
| | DNS | | | NOT your destination |
| | | Firewall | | |
+---------------------+ +-------------------------------+ +----------------------+
^ ^ ^
| | |
DNS | | |
| | |
V | |
+------------------------------+ encrypted DNS | |
| | <------------------------------/ |
| AdGuardHome --> Unbound | | TCP / Onion Encryption
| DNS Filtering + Forwarding | |
| | DNS / Onion Encryption |
| 10.192.0.1 / DNS Port 9053 | |
| TOR TRANSPARENT PROXY | |
| | v
+------------------------------+ +----------------------+
| |
| TOR RELAY NODE |
| |
| NEITHER knows |
| your IP |
| NOR your destination |
| |
+----------------------+
^
|
| TCP / Onion Encryption
|
DNS / Onion Encryption |
|
v
+----------------------+
| |
| TOR EXIT NODE |
| |
| CANNOT know your IP |
| but KNOWS |
| your destination |
| |
+----------------------+
^
|
DNS | TCP
|
v
+--------------+
| |
| INTERNET |
| |
+--------------+
Чтобы установить пакет tor, выполните:
sudo apt install -y tor
Начните с резервного копирования стандартной конфигурации Tor:
sudo cp /etc/tor/torrc /etc/tor/torrc.bak
Затем включите базовое ведение журнала и настройте Tor для работы в качестве фоновой службы:
sudo sed -i 's|^#Log notice file /var/log/tor/notices.log|Log notice file /var/log/tor/notices.log|; s|^#RunAsDaemon 1|RunAsDaemon 1|; s|^#DataDirectory /var/lib/tor|DataDirectory /var/lib/tor|' /etc/tor/torrc
Добавьте в файл torrc следующую конфигурацию:
sudo tee -a /etc/tor/torrc > /dev/null <<EOF
# Tor Transparent Proxy
VirtualAddrNetworkIPv4 10.192.0.0/12
AutomapHostsSuffixes .onion,.exit
AutomapHostsOnResolve 1
# Bind Transparent Proxy & DNSPort to localhost
TransPort 10.192.0.1:9040
DNSPort 10.192.0.1:9053
EOF
Остановите службу Tor и отключите автозапуск при загрузке, так как мы будем управлять службой Tor вручную:
sudo systemctl stop tor@default
sudo systemctl disable tor@default
Как и в случае с настройкой WireGuard, мы будем использовать выделенный интерфейс NetworkManager для активации и деактивации прозрачного прокси Tor. Создайте и настройте фиктивный интерфейс с именем torproxy:
sudo nmcli con add type dummy ifname torproxy con-name torproxy ipv4.method manual ipv4.addresses 10.192.0.1/32
sudo nmcli con modify torproxy ipv4.ignore-auto-routes yes
sudo nmcli con modify torproxy ipv4.never-default yes
sudo nmcli con modify torproxy ipv4.dns 10.192.0.1
sudo nmcli con modify torproxy autoconnect no
После создания подключения рекомендуется сразу его отключить (на случай автоматического подключения):
sudo nmcli con down torproxy
Конфигурация межсетевого экрана для Tor сложнее, чем для WireGuard, так как требует явного перенаправления трафика и дополнительных мер защиты. Мы будем использовать предварительно настроенный набор правил, который можно загрузить из нашего репозитория.
Сначала убедитесь, что существует структура каталогов для конфигураций межсетевого экрана:
[ -d ~/script ] || mkdir ~/script && [ -d ~/script/nftables ] || mkdir ~/script/nftables
Затем загрузите конфигурацию межсетевого экрана для Tor:
sudo curl -L -o /home/admin/script/nftables/torproxy.conf "https://codeberg.org/term7/Going-Dark/raw/branch/main/Pi%20Configuration%20Files/nftables/torproxy.conf"
Этот межсетевой экран реализует все меры защиты, описанные в разделе 18 МЕЖСЕТЕВОЙ ЭКРАН, а также:
Он также улучшает конфиденциальность, полностью блокируя ICMP-эхо-запросы из интернета. Кроме того, он удаляет все фрагментированные IP-пакеты, которые могут использоваться для сканирования или уклонения.
Управление трафиком, специфичное для Tor
Чтобы предотвратить петли маршрутизации или сбои в работе сервисов, межсетевой экран явно разрешает трафик, создаваемый самим процессом Tor, обходить перенаправление. Это гарантирует, что Tor может устанавливать цепочки без помех со стороны межсетевого экрана.
Цепочка forward в этой настройке межсетевого экрана строго ограничена. Она разрешает пересылку только трафика, который был маршрутизирован через Tor, и блокирует всю остальную межинтерфейсную пересылку для поддержания сильной изоляции.
Специальная обработка DNS
Межсетевой экран не отправляет DNS-трафик напрямую на DNS-порт Tor (9053). Вместо этого он продолжает перенаправлять DNS-запросы в AdGuardHome (порт 5357), который, в свою очередь, передаёт их в Unbound. Мы настроим Unbound так, чтобы он передавал все DNS-запросы на DNSPort Tor (9053), сохраняя фильтрацию DNS при полной анонимизации через Tor.
Снова будем использовать скрипт-диспетчер NetworkManager для автоматического переключения межсетевого экрана и конфигурации DNS Unbound при подключении или отключении интерфейса torproxy. Кроме того, скрипт будет динамически запускать и останавливать сервис Tor по мере необходимости.
Когда Tor активен, Unbound переходит в «режим Tor»: вместо выполнения рекурсивного разрешения DNS с использованием корневых серверов он передаёт все DNS-запросы через прозрачный прокси Tor. Эти запросы затем разрешаются узлом выхода Tor.
Однако, поскольку встроенный в Tor резолвер DNS не возвращает записи, связанные с DNSSEC (например, DNSKEY или RRSIG), Unbound не может проверять DNSSEC в этой конфигурации, даже если он настроен на её обязательное использование. Чтобы предотвратить сбои в разрешении DNS и доступе в интернет, наш скрипт-диспетчер временно включает разрешительный режим DNSSEC и разрешает запросы к localhost (DNSPort Tor), когда прокси активен. При деактивации интерфейса восстанавливаются исходные безопасные настройки. Кроме того, скрипт перезапускает fail2ban, чтобы восстановить ранее заблокированные IP-адреса.
Создайте скрипт-диспетчер:
sudo tee /etc/NetworkManager/dispatcher.d/torproxy-handler > /dev/null << 'EOF'
#!/bin/bash
# Define Interfaces
TOR_INTERFACE="torproxy"
# Define Config Files
TOR_RULES="/home/admin/script/nftables/torproxy.conf"
DEFAULT_RULES="/etc/nftables.conf"
UNBOUND_MAIN_CONFIG="/etc/unbound/unbound.conf.d/unbound-dnssec.conf"
UNBOUND_CONFIG="/etc/unbound/unbound.conf.d/local-zones.conf"
# Define TorProxy DNS Config
TOR_DNS_CONFIG="# Upstream DNS via Tor\nforward-zone:\n name: \".\"\n forward-addr: 10.192.0.1@9053"
case "$1" in
$TOR_INTERFACE)
case "$2" in
up)
# Apply Tor firewall rules
/usr/sbin/nft -f "$TOR_RULES"
# Start Tor service
sudo systemctl start tor@default
# Edit Unbound main configuration
sed -i 's/do-not-query-localhost: yes/do-not-query-localhost: no/' "$UNBOUND_MAIN_CONFIG"
sed -i 's/val-permissive-mode: no/val-permissive-mode: yes/' "$UNBOUND_MAIN_CONFIG"
# Append TorProxy DNS to Unbound if not already present
if ! grep -Fxq "$TOR_DNS_CONFIG" "$UNBOUND_CONFIG"; then
echo -e "\n$TOR_DNS_CONFIG" | sudo tee -a "$UNBOUND_CONFIG" > /dev/null
fi
sudo systemctl restart unbound
sudo systemctl restart fail2ban
;;
down)
# Restore default nftables rules
/usr/sbin/nft -f "$DEFAULT_RULES"
# Stop Tor service
sudo systemctl stop tor@default
# Restore Unbound main configuration
sed -i 's/do-not-query-localhost: no/do-not-query-localhost: yes/' "$UNBOUND_MAIN_CONFIG"
sed -i 's/val-permissive-mode: yes/val-permissive-mode: no/' "$UNBOUND_MAIN_CONFIG"
# Remove TorProxy DNS Config
sed -i '/fallback-enabled: yes/,$d' "$UNBOUND_CONFIG"
echo " fallback-enabled: yes" | sudo tee -a "$UNBOUND_CONFIG" > /dev/null
sudo systemctl restart unbound
sudo systemctl restart fail2ban
;;
esac
;;
esac
EOF
Сделайте скрипт исполняемым:
sudo chmod +x /etc/NetworkManager/dispatcher.d/torproxy-handler
Чтобы запустить прозрачный прокси Tor:
sudo nmcli con up torproxy
Чтобы остановить прозрачный прокси Tor:
sudo nmcli con down torproxy
Чтобы проверить, что ваш Raspberry Pi корректно маршрутизирует трафик через сеть Tor, выполните на устройстве следующую команду:
curl https://check.torproject.org/api/ip
Вы должны получить JSON-ответ с IP-адресом узла выхода Tor, что подтвердит анонимизацию исходящего трафика.
Чтобы подтвердить, что подключённое клиентское устройство — например, ваш Mac — также маршрутизируется через Tor, откройте браузер и перейдите по адресу:
https://check.torproject.org
Если всё работает правильно, на странице отобразится сообщение о том, что ваш трафик идёт из сети Tor.
Чтобы проверить возможные утечки DNS, посетите:
https://dnsleaktest.com
Если вы видите свой домашний IP-адрес или IP-адрес DNS-резолвера, который вы настроили вручную на устройстве или маршрутизаторе, это указывает на утечку DNS. В этом случае ваш Прозрачный прокси Tor не изолирует DNS-трафик должным образом, и, возможно, потребуется пересмотреть конфигурацию, чтобы убедиться, что DNS-запросы также направляются через Tor.
На этом этапе ваш Raspberry Pi должен быть полностью функциональным и работать так, как задумано. Пока что переключение между различными режимами всё ещё требует входа по SSH и использования командной строки из учётной записи admin.
Запустить точку доступа:
sudo nmcli con up Hotspot
Остановить точку доступа:
sudo nmcli con down Hotspot
Включить WireGuard:
sudo nmcli con up term7.wireguard
Отключить WireGuard:
sudo nmcli con down term7.wireguard
Включить Прозрачный прокси Tor:
sudo nmcli con up torproxy
Отключить Прозрачный прокси Tor:
sudo nmcli con down torproxy
⚠️ Важно: Никогда не запускайте WireGuard и Tor одновременно. Всегда отключайте один перед активацией другого — одновременная работа обоих вызовет конфликты и нарушит маршрутизацию.
Это была Часть 1 данного репозитория. В следующих разделах Части 2 мы покажем, как настроить удобный интерфейс управления, к которому можно подключиться локально из браузера по адресу: https://going.dark
Это начало Части 2.
В Части 1 этого руководства мы создали серверные службы на Raspberry Pi. Теперь пришло время объединить всё это в локальном веб-интерфейсе, который работает непосредственно на Pi и упрощает управление службами.
Интерфейс предоставляется локально через USB-C (192.168.77.1) на ваш рабочий компьютер. Он интегрирует два приложения Flask (установленных под стандартной учётной записью пользователя term7):
portal.py — управляет сетевыми функциями, такими как VPN, Прокси Tor и Точка доступа.
config.py — управляет системными функциями, такими как выключение, перезагрузка, автоматическая генерация нового случайного имени хоста и MAC-адреса, а также отображение диагностической информации системы и данных о времени.
Оба приложения предоставляют простые элементы управления на основе кнопок. Кроме того, интерфейс встраивает панель управления AdGuard Home, которую мы настроили ранее в Части 1.
В следующих шагах мы:
/var/www/going.dark.Обратите внимание:
⚠️ Предупреждение: Всегда проверяйте любой код перед его загрузкой или запуском. Не доверяйте слепо этому руководству или любому другому. Убедитесь, что код легитимен и безопасен. Если вы обнаружите ошибки, неиспользуемый код или у вас есть предложения по улучшениям, пожалуйста, сообщите нам!
Готовый веб-интерфейс управления позволит вам:
Запуск приложений Flask под стандартной учётной записью с тщательно ограниченными правами sudo уменьшает поверхность атаки, предотвращает случайные изменения на уровне системы и соответствует установленным практикам безопасности. По этой причине мы позже установим наши приложения Flask под стандартной учётной записью пользователя (term7). Однако для обеспечения необходимой функциональности term7 должен получить права суперпользователя для небольшого набора команд, а именно тех, которые требуются для управления сетью (nmcli), сканирования сетей Wi-Fi (iw) и выполнения системных действий, таких как reboot и shutdown.
Переключитесь на учётную запись admin:
su admin
Создайте новое правило polkit, чтобы предоставить term7 необходимые привилегии NetworkManager:
sudo sh -c 'cat >/etc/polkit-1/rules.d/10-allow-term7-nm.rules << "EOF"
polkit.addRule(function(action, subject) {
if (subject.user == "term7") {
if (
action.id == "org.freedesktop.NetworkManager.network-control" ||
action.id == "org.freedesktop.NetworkManager.settings.modify.system" ||
action.id == "org.freedesktop.NetworkManager.wifi.share.open" ||
action.id == "org.freedesktop.NetworkManager.wifi.share.protected" ||
action.id == "org.freedesktop.NetworkManager.enable-disable-wifi"
) {
return polkit.Result.YES;
}
}
});
EOF'
Перезапустите polkit, чтобы применить новое правило:
sudo systemctl restart polkit || sudo systemctl restart polkit-1
В разделе 04 КОНТРОЛЬ ДОСТУПА ПОЛЬЗОВАТЕЛЕЙ мы уже настроили файл /etc/sudoers.d/common_users, чтобы разрешить term7 выполнять команды reboot и shutdown.
Теперь мы расширим этот файл дополнительными привилегиями для:
- iw (сканирование Wi-Fi и дамп станций)
- ограниченной команды nmcli, которая показывает только PSK точки доступа. Это понадобится позже, когда приложение Flask (с использованием segno) сгенерирует QR-код после того, как пользователь введёт новый SSID и пароль и подтвердит нажатием Enter.
Выполните следующее:
NMCLI="$(command -v nmcli)"
IW="$(command -v iw)"
sudo sed -i "s|\$|, ${IW} dev wlx00c0caae6319 scan trigger, ${IW} dev wlx00c0caae6319 scan dump, ${IW} dev wlan0 station dump, ${NMCLI} -s -g 802-11-wireless-security.psk connection show Hotspot|" /etc/sudoers.d/common_users
Привилегии разделены между polkit и sudoers не случайно. Операции NetworkManager, такие как подключение, отключение и управление профилями, обрабатываются через polkit, так как они чётко соответствуют его действиям D-Bus и считаются безопасными для стандартного пользователя после явного разрешения. В то же время команды вроде сканирования Wi-Fi, получения PSK точки доступа или выполнения системных действий, таких как reboot и shutdown, остаются заблокированными в sudoers. Это разделение гарантирует, что у term7 есть только те точные разрешения, которые необходимы, следуя принципу минимальных привилегий, при этом позволяя веб-интерфейсу работать в полной мере.
Прежде чем создавать веб-интерфейс управления, сначала нужно настроить NGINX и создать второй SSL-сертификат для нового локального сайта going.dark. Этот процесс очень похож на то, что мы делали в 16 SSL-СЕРТИФИКАТ и 17 НАСТРОЙКА ОБРАТНОГО ПРОКСИ NGINX, где мы сгенерировали самоподписанный SSL-сертификат для adguard.home и настроили NGINX как обратный прокси. На этом этапе мы повторно используем существующий самоподписанный центр сертификации term7-CA для выпуска нового SSL-сертификата специально для going.dark.
Перейдите в каталог конфигурации SSL:
cd ~/tools/CA/SSL
Создайте файл конфигурации OpenSSL для going.dark:
echo '[ req ]
default_bits = 2048
default_md = sha256
prompt = no
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
CN = going.dark
[ v3_req ]
subjectAltName = @alt_names
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ alt_names ]
DNS.1 = going.dark
IP.1 = 192.168.77.1' | sudo tee /home/admin/tools/CA/SSL/openssl-goingdark.cnf > /dev/null
Сгенерируйте закрытый ключ для going.dark:
openssl genrsa -out ~/tools/CA/SSL/going.dark.key 2048
Создайте запрос на подпись сертификата (CSR):
openssl req -new -key going.dark.key -out going.dark.csr -config openssl-goingdark.cnf
Подпишите запрос на подпись сертификата (CSR) существующим локальным центром сертификации (term7-CA):
sudo openssl x509 -req -in ~/tools/CA/SSL/going.dark.csr -CA ~/tools/CA/term7-CA.pem -CAkey ~/tools/CA/term7-CA.key -CAcreateserial -out ~/tools/CA/SSL/going.dark.crt -days 90 -extensions v3_req -extfile ~/tools/CA/SSL/openssl-goingdark.cnf
Создайте полный сертификат:
cat ~/tools/CA/SSL/going.dark.crt ~/tools/CA/term7-CA.pem > ~/tools/CA/SSL/going.dark-fullchain.crt
Вам не нужно заново доверять этим сертификатам на вашем Raspberry Pi или переносить локальный центр сертификации (term7-CA) на ваш Mac, так как это уже было сделано в 16 SSL-СЕРТИФИКАТ! Чтобы включить going.dark в существующий скрипт обновления сертификатов, выполните:
sed -i '/^DOMAINS=(/ {/going\.dark/! s/\(adguard\.home"\)[[:space:]]*)/\1 "going.dark")/ }' /home/admin/script/SSL/renew-cert.sh
Создайте корневой каталог веб-сайта:
sudo mkdir -p /var/www/going.dark
Добавьте простую тестовую веб-страницу. Позже мы заменим её интерфейсом управления:
echo '<!DOCTYPE html>
<html>
<head>
<title>Going Dark</title>
</head>
<body>
<h1>Welcome to going.dark</h1>
This is your simple test site.</p>
</body>
</html>' | sudo tee /var/www/going.dark/index.html > /dev/null
Установите правильные права владения:
sudo chown -R www-data:www-data /var/www/going.dark
Создайте конфигурацию NGINX:
echo 'server {
listen 443 ssl http2;
server_name going.dark;
ssl_certificate /home/admin/tools/CA/SSL/going.dark-fullchain.crt;
ssl_certificate_key /home/admin/tools/CA/SSL/going.dark.key;
location / {
root /var/www/going.dark;
index index.html;
}
}
server {
listen 80;
server_name going.dark;
return 301 https://$host$request_uri;
}' | sudo tee /etc/nginx/sites-available/nginx-goingdark > /dev/null
Активируйте новую конфигуцию сайта NGINX:
sudo ln -s /etc/nginx/sites-available/nginx-goingdark /etc/nginx/sites-enabled/
Проверьте конфигурацию на ошибки:
sudo nginx -t
Если тест пройдён успешно, перезапустите NGINX:
sudo systemctl restart nginx
Добавьте going.dark в файл /etc/hosts на вашем Mac и Raspberry Pi, чтобы он разрешался локально:
sudo sed -i.bak 's/\(adguard\.home\)\([^ ]*\)/\1 going.dark\2/' /etc/hosts && sudo rm -f /etc/hosts.bak
Чтобы убедиться, что всё настроено правильно, откройте веб-браузер на вашем Mac и перейдите по адресу: https://going.dark
Вы должны увидеть простую тестовую страницу, созданную ранее.
На этом этапе у нас уже работает AdGuard Home локально на 127.0.0.1:3000.
Наше приложение portal.py позже будет работать на 127.0.0.1:5001, а config.py — на 127.0.0.1:5002.
Следующая команда запишет финальную конфигурацию NGINX для going.dark. Это перезапишет вашу предыдущую конфигурацию сайта NGINX:
echo 'server {
listen 192.168.77.1:443 ssl http2;
server_name going.dark;
ssl_certificate /home/admin/tools/CA/SSL/going.dark-fullchain.crt;
ssl_certificate_key /home/admin/tools/CA/SSL/going.dark.key;
# ---- Minimal global hardening ----
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), bluetooth=(), midi=(), usb=()" always;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Strict-Transport-Security "max-age=15552000" always; # ~180 days
# ---- Static site root ----
location / {
root /var/www/going.dark;
index index.html;
}
# ---- Canonicalize /portal -> /portal/ ----
location = /portal { return 301 /portal/; }
# ---- Serve portal assets as static files ----
location = /portal/portal.css {
alias /var/www/going.dark/portal/portal.css;
default_type text/css;
add_header Cache-Control "public, max-age=300";
}
location = /portal/portal.js {
alias /var/www/going.dark/portal/portal.js;
default_type application/javascript;
add_header Cache-Control "public, max-age=300";
}
# ---- Proxy /portal/ to the Flask app on localhost:5001 ----
location /portal/ {
proxy_pass http://127.0.0.1:5001/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
# ---- Canonicalize /config -> /config/ ----
location = /config { return 301 /config/; }
# ---- Serve config assets as static files ----
location = /config/config.css {
alias /var/www/going.dark/config/config.css;
default_type text/css;
add_header Cache-Control "public, max-age=300";
}
location = /config/config.js {
alias /var/www/going.dark/config/config.js;
default_type application/javascript;
add_header Cache-Control "public, max-age=60";
}
# ---- Proxy /config/ to the Flask app on localhost:5002 ----
location /config/ {
proxy_pass http://127.0.0.1:5002/;
# Standard proxy headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
# ---- Canonicalize /adguard -> /adguard/ ----
location = /adguard { return 301 /adguard/; }
# ---- Same-origin path mount of AdGuard Home UI under /adguard/ ----
location ^~ /adguard/ {
# Strip the /adguard/ prefix before proxying upstream
proxy_pass http://127.0.0.1:3000/;
# Headers
proxy_set_header Host adguard.home; # upstream expects this
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support (live updates/logs)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
proxy_send_timeout 300s;
# Cookie & path scoping so sessions are first-party to going.dark under /adguard/
proxy_cookie_domain adguard.home going.dark;
proxy_cookie_path / /adguard/;
# ---- Rewrite upstream redirects (Location headers) to stay under /adguard/ ----
proxy_redirect ~^(/.*)$ /adguard$1;
proxy_redirect http://127.0.0.1:3000/ /adguard/;
proxy_redirect https://127.0.0.1:3000/ /adguard/;
proxy_redirect https://adguard.home/ /adguard/;
# ---- Rewrite in-body root-relative URLs (HTML/CSS/JS/JSON) ----
proxy_set_header Accept-Encoding ""; # allow sub_filter to see text (disable upstream compression)
sub_filter_once off;
sub_filter_types text/css application/javascript application/json;
sub_filter 'href="/' 'href="/adguard/';
sub_filter 'src="/' 'src="/adguard/';
sub_filter 'action="/' 'action="/adguard/';
sub_filter 'content="/' 'content="/adguard/';
sub_filter 'url(/' 'url(/adguard/';
sub_filter 'fetch("/' 'fetch("/adguard/';
sub_filter "fetch('/" "fetch('/adguard/";
sub_filter 'XMLHttpRequest("/' 'XMLHttpRequest("/adguard/';
sub_filter "XMLHttpRequest('/" "XMLHttpRequest('/adguard/";
# Avoid caching admin UI/API
add_header Cache-Control "no-store" always;
# ---- Silence ad-tech header ----
proxy_hide_header Permissions-Policy;
proxy_hide_header Origin-Trial;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=(), bluetooth=(), midi=(), usb=()" always;
}
}
# HTTP -> HTTPS redirect for going.dark
server {
listen 192.168.77.1:80;
server_name going.dark;
return 301 https://$host$request_uri;
}
' | sudo tee /etc/nginx/sites-available/nginx-goingdark > /dev/null
На данном этапе статическая веб-страница и приложения Flask (portal.py и config.py) ещё не установлены или не запущены.
Из-за этого перезапуск NGINX сейчас приведёт к ошибке при попытке проксировать запросы к этим сервисам.
Не перезапускайте NGINX пока. Продолжите настройку приложений Flask сначала, и только потом перезагрузите или перезапустите NGINX.
Войдите в систему под учётной записью admin и установите необходимые системные пакеты:
sudo apt install -y python3-flask python3-venv python3-pip
Приложение Flask portal.py предоставляет веб-интерфейс, работающий на 127.0.0.1:5001 и доступный по адресу https://going.dark/portal. Шаблоны HTML встроены непосредственно в приложение, а вспомогательные файлы CSS (portal.css) и JavaScript (portal.js) будут обслуживаться из /var/www/going.dark/portal.
Через этот интерфейс вы сможете подключаться и отключаться от сетей Wi-Fi, запускать и останавливать точку доступа (с новым SSID и паролем, задаваемыми непосредственно из интерфейса), генерировать QR-код для удобного подключения мобильных клиентов к точке доступа, подключаться к вашему WireGuard VPN и маршрутизировать весь трафик через прозрачный прокси Tor. Приложение также отображает ваш текущий IP-адрес и его геолокацию на основе этого IP.
Это приложение интегрируется со следующими компонентами из Части 1:
Поскольку наши приложения Flask будут запускаться в стандартной учётной записи пользователя, необходимо выйти из учётной записи администратора:
exit
От имени пользователя term7 создайте и перейдите в каталог приложения:
mkdir -p ~/portal && cd ~/portal
Создайте виртуальное окружение для приложения Flask:
python3 -m venv .venv
Активируйте виртуальное окружение:
. .venv/bin/activate
Установите и зафиксируйте необходимые библиотеки Python:
pip install --upgrade pip
pip install gunicorn flask segno
pip freeze > requirements.txt
Деактивируйте виртуальное окружение:
deactivate
Загрузите скрипт приложения Flask в папку приложения:
curl -L -o /home/term7/portal/portal.py "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Flask%20Apps/portal_app/portal.py"
Вернитесь в учётную запись admin:
su admin
Создайте корневой веб-каталог для ресурсов портала:
sudo mkdir -p /var/www/going.dark/portal
Загрузите файлы фронтенда:
sudo curl -L -o /var/www/going.dark/portal/portal.js "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/portal/portal.js"
sudo curl -L -o /var/www/going.dark/portal/portal.css "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/portal/portal.css"
portal.pyСоздайте файл модуля сервиса:
sudo tee /etc/systemd/system/portal.service >/dev/null <<'EOF'
[Unit]
Description=Portal App
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=term7
Group=term7
WorkingDirectory=/home/term7/portal
Environment="PYTHONUNBUFFERED=1"
Environment="PATH=/home/term7/portal/.venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
ExecStart=/home/term7/portal/.venv/bin/python -m gunicorn -w 2 -k gthread --threads 8 --bind 127.0.0.1:5001 --access-logfile - --error-logfile - portal:app
Restart=on-failure
RestartSec=2
[Install]
WantedBy=multi-user.target
EOF
Перезагрузите systemd, затем активируйте и запустите сервис:
sudo systemctl daemon-reload
sudo systemctl enable --now portal.service
Приложение Flask config.py предоставляет веб-интерфейс, работающий на 127.0.0.1:5002 и доступный по адресу https://going.dark/config. Как и в случае с portal.py, шаблоны HTML встроены непосредственно в приложение, а вспомогательные файлы CSS (config.css) и JavaScript (config.js) будут обслуживаться из /var/www/going.dark/config.
Через этот интерфейс вы можете выключить и перезагрузить Raspberry Pi. При перезагрузке приложение автоматически генерирует новую случайную идентичность устройства, назначая новый имя хоста и новый MAC-адрес. Кроме того, оно отображает системные часы, текущий NTP-сервер (последний узел, использованный для синхронизации времени), а также в панели в стиле MOTD показывает диагностическую информацию системы, включая текущую нагрузку, количество запущенных процессов, температуру процессора, использование памяти, использование swap и время работы. Приложение также напрямую интегрируется с веб-интерфейсом, который мы настроим в следующей главе: когда устройство отключено от сети, большинство элементов затемняется, а при возвращении онлайн они снова появляются.
Это приложение интегрируется со следующими компонентами из Части 1:
Поскольку наши приложения Flask будут запускаться в стандартной учётной записи пользователя, снова выйдите из сеанса администратора:
exit
От имени пользователя term7 создайте и перейдите в каталог приложения:
mkdir -p ~/config && cd ~/config
Создайте виртуальное окружение для приложения Flask:
python3 -m venv .venv
Активируйте виртуальное окружение:
. .venv/bin/activate
Установите и зафиксируйте необходимые библиотеки Python:
pip install --upgrade pip
pip install gunicorn flask
pip freeze > requirements.txt
Деактивируйте виртуальное окружение:
deactivate
Загрузите скрипт приложения Flask в папку приложения:
curl -L -o /home/term7/config/config.py "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Flask%20Apps/config_app/config.py"
Вернитесь в учётную запись admin:
su admin
Создайте корневой веб-каталог для ресурсов конфигурации:
sudo mkdir -p /var/www/going.dark/config
Загрузите файлы фронтенда:
sudo curl -L -o /var/www/going.dark/config/config.js "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/config/config.js"
sudo curl -L -o /var/www/going.dark/config/config.css "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/config/config.css"
config.pyСоздайте файл модуля сервиса:
sudo tee /etc/systemd/system/config.service >/dev/null <<'EOF'
[Unit]
Description=Config App
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=term7
Group=term7
WorkingDirectory=/home/term7/config
Environment="PYTHONUNBUFFERED=1"
Environment="PATH=/home/term7/config/.venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin"
ExecStart=/home/term7/config/.venv/bin/python -m gunicorn -w 2 -k gthread --threads 8 --bind 127.0.0.1:5002 --access-logfile - --error-logfile - config:app
Restart=on-failure
RestartSec=2
[Install]
WantedBy=multi-user.target
EOF
Перезагрузите systemd, затем активируйте и запустите сервис:
sudo systemctl daemon-reload
sudo systemctl enable --now config.service
Не перезапускайте NGINX пока. Продолжите настройку фронтенд-сайта и только потом перезагрузите или перезапустите NGINX.
После развёртывания фронтенд-сайт будет доступен по адресу https://going.dark. Макет intentionally простой: страница содержит три выдвижные панели, которые можно открывать и закрывать, каждая из которых встраивает iframe: Панель 1 размещает Portal.app, Панель 2 открывает Config.app, а Панель 3 загружает AdGuard Home.
Анимированный фон показывает умножающиеся шары, отражающие модель конфиденциальности Tor: один пользователь выделяется, но по мере появления новых пользователей и выравнивания трафика наблюдателю становится сложнее определить, кто есть кто. Основная идея заключается в том, что по мере роста толпы уменьшается уверенность в первоначальной идентичности.
Каждый файл содержит комментарии, описывающие назначение его разделов:
Главная страница
/var/www/going.dark/index.html
/var/www/going.dark/style.css
Ресурсы приложения Flask
/var/www/going.dark/portal/portal.js
/var/www/going.dark/portal/portal.css
/var/www/going.dark/config/config.js
/var/www/going.dark/config/config.css
Вспомогательные скрипты JavaScript
/var/www/going.dark/assets/js/adguard.js
/var/www/going.dark/assets/js/canvas.js
/var/www/going.dark/assets/js/drawers.js
/var/www/going.dark/assets/js/power.js
Ресурсы
/var/www/going.dark/assets/fonts/*
/var/www/going.dark/assets/favicon.png
/var/www/going.dark/assets/term7.svg
Создайте необходимые каталоги:
sudo mkdir -p /var/www/going.dark/assets/{js,fonts}
Загрузите HTML-, CSS- и JavaScript-файлы:
sudo curl -fL -o /var/www/going.dark/index.html "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/index.html"
sudo curl -fL -o /var/www/going.dark/style.css "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/style.css"
sudo curl -fL -o /var/www/going.dark/assets/js/adguard.js "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/js/adguard.js"
sudo curl -fL -o /var/www/going.dark/assets/js/canvas.js "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/js/canvas.js"
sudo curl -fL -o /var/www/going.dark/assets/js/drawers.js "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/js/drawers.js"
sudo curl -fL -o /var/www/going.dark/assets/js/power.js "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/js/power.js"
Загрузите значки и шрифты:
sudo curl -fL -o /var/www/going.dark/assets/favicon.png "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/favicon.png"
sudo curl -fL -o /var/www/going.dark/assets/term7.svg "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/term7.svg"
sudo curl -fL -o /var/www/going.dark/assets/fonts/ANON-DIGITAL_italic.ttf "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/ANON-DIGITAL_italic.ttf"
sudo curl -fL -o /var/www/going.dark/assets/fonts/ANON-DIGITAL_italic.woff "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/ANON-DIGITAL_italic.woff"
sudo curl -fL -o /var/www/going.dark/assets/fonts/ANON-DIGITAL_italic.woff2 "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/ANON-DIGITAL_italic.woff2"
sudo curl -fL -o /var/www/going.dark/assets/fonts/ANON-DIGITAL_normal.ttf "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/ANON-DIGITAL_normal.ttf"
sudo curl -fL -o /var/www/going.dark/assets/fonts/ANON-DIGITAL_normal.woff "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/ANON-DIGITAL_normal.woff"
sudo curl -fL -o /var/www/going.dark/assets/fonts/ANON-DIGITAL_normal.woff2 "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/ANON-DIGITAL_normal.woff2"
sudo curl -fL -o /var/www/going.dark/assets/fonts/Handwriting.ttf "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/Handwriting.ttf"
sudo curl -fL -o /var/www/going.dark/assets/fonts/Handwriting.woff "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/Handwriting.woff"
sudo curl -fL -o /var/www/going.dark/assets/fonts/Handwriting.woff2 "https://codeberg.org/term7/Going-Dark/raw/branch/main/Web%20Interface%20Frontend%20Website/assets/fonts/Handwriting.woff2"
Поскольку файлы были загружены от имени root, по умолчанию они принадлежат root. Чтобы обеспечить единообразие прав собственности во всём корневом каталоге веб-сервера, настройте разрешения следующим образом:
sudo chown -R www-data:www-data /var/www/going.dark
Наконец, перезапустите NGINX, чтобы изменения вступили в силу:
sudo nginx -t
sudo systemctl restart nginx