SSL Inspector — это TLS-инспекционный прокси-сервер (SSL MITM), который перехватывает и расшифровывает HTTPS-трафик «на лету», не вызывая ошибок в браузере. К нему прилагается веб-дашборд с журналом всех соединений.
Браузер ──HTTP CONNECT──► Прокси :8080
│
┌──────────┴──────────┐
│ Bypass-домен? │
│ (банки, госуслуги…) │
└────┬────────────────┘
Нет │ Да
│ └──► Прозрачный туннель (TCP)
▼
Генерация сертификата
для example.com, подписан
нашим CA
│
┌──────────┴──────────┐
│ │
TLS с клиентом TLS с сервером
(наш сертификат) (реальный сертификат)
│ │
└──────── pipe ────────┘
│
OnPlaintext(data)
← расшифрованный трафик →
DPI, логирование, блокировка
| Компонент | Файл | Описание |
|---|---|---|
Inspector |
internal/inspector/inspector.go |
Ядро: перехват, генерация сертификатов, pipe |
GenerateCA |
internal/inspector/ca_gen.go |
Генерация корневого CA |
Dashboard |
internal/dashboard/server.go |
Веб-UI + REST API |
main |
cmd/ssl-inspector/main.go |
CLI: gen-ca, start |
go mod tidygo run ./cmd/ssl-inspector gen-caСоздаст два файла:
certs/ca.crt— сертификат CA (нужно установить в систему/браузер)certs/ca.key— приватный ключ CA (храните в секрете!)
- Двойной клик на
certs/ca.crt - «Установить сертификат» → «Локальный компьютер»
- «Поместить все сертификаты в следующее хранилище» → «Доверенные корневые центры сертификации»
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain certs/ca.crtsudo cp certs/ca.crt /usr/local/share/ca-certificates/ssl-inspector-ca.crt
sudo update-ca-certificatesНастройки → Приватность и защита → Сертификаты → Просмотр сертификатов →
Импортировать → выбрать ca.crt → Отметить «Доверять при идентификации сайтов»
go run ./cmd/ssl-inspector startЗапустится:
- Прокси:
http://0.0.0.0:8080 - Дашборд:
http://0.0.0.0:8081
Укажите HTTP-прокси: хост 127.0.0.1, порт 8080.
google-chrome --proxy-server="http://127.0.0.1:8080"curl -x http://127.0.0.1:8080 https://example.com| Переменная | По умолчанию | Описание |
|---|---|---|
PROXY_ADDR |
0.0.0.0:8080 |
Адрес прокси |
DASH_ADDR |
0.0.0.0:8081 |
Адрес дашборда |
CA_KEY |
certs/ca.key |
Путь к ключу CA |
CA_CERT |
certs/ca.crt |
Путь к сертификату CA |
В cmd/ssl-inspector/main.go в поле BypassDomains добавьте домены,
которые не нужно инспектировать:
BypassDomains: []string{
"sberbank.ru",
"gosuslugi.ru",
"nalog.ru",
"pfr.gov.ru",
},Субдомены учитываются автоматически: если в списке example.com,
то sub.example.com тоже будет пропущен.
Для анализа/логирования расшифрованного трафика используйте хук OnPlaintext:
ins.OnPlaintext = func(event *inspector.TrafficEvent, data []byte, direction string) {
// direction = "request" (клиент → сервер) или "response" (сервер → клиент)
if direction == "request" {
// Пример: ищем пароли в теле POST-запроса
if bytes.Contains(data, []byte("password=")) {
log.Warnf("Возможная передача пароля на %s", event.Host)
}
}
// Пример: блокируем определённые запросы
// (для блокировки нужно разрывать соединение — см. раздел расширения)
}type TrafficEvent struct {
ID uint64 // Уникальный ID соединения
Timestamp time.Time // Время начала соединения
Host string // Хост назначения (example.com)
ClientAddr string // IP:порт клиента
Bytes int64 // Передано байт
Intercepted bool // true = инспекция, false = bypass
TLSVersion string // "TLS 1.3", "TLS 1.2", ...
CipherSuite string // Название шифра
ServerCert string // Subject исходного сертификата сервера
}| Метод | Путь | Описание |
|---|---|---|
| GET | /api/stats |
Статистика инспектора |
| GET | /api/events?limit=50 |
Последние N соединений |
| GET | /api/ca.crt |
Скачать CA-сертификат |
{
"total_conns": 142,
"intercepted_conns": 138,
"bypassed_conns": 4,
"total_mb": 15.7,
"cert_cache_size": 23,
"uptime_seconds": 3612.5,
"started_at": "2024-01-15T10:30:00Z"
}В хуке OnPlaintext или в HandleCONNECT добавьте проверку:
// В HandleCONNECT, перед генерацией сертификата:
if host == "blocked-site.com" {
http.Error(w, "Заблокировано политикой безопасности", http.StatusForbidden)
return
}ins.OnPlaintext = func(event *inspector.TrafficEvent, data []byte, direction string) {
keywords := []string{"password", "token", "secret", "api_key"}
for _, kw := range keywords {
if bytes.Contains(bytes.ToLower(data), []byte(kw)) {
log.Warnf("[DPI] Ключевое слово '%s' в трафике %s", kw, event.Host)
}
}
}ins.OnPlaintext = func(event *inspector.TrafficEvent, data []byte, direction string) {
fname := fmt.Sprintf("traffic/%d-%s-%s.bin", event.ID, event.Host, direction)
os.WriteFile(fname, data, 0600)
}В main.go в обработчик прокси добавьте ветку для не-CONNECT запросов
с использованием httputil.ReverseProxy.
- TLS-инспекция допустима только на устройствах и в сетях, которые вы администрируете и на которые дали явное письменное согласие все пользователи.
- В корпоративной среде: уведомите сотрудников в ПВТР или при подписании трудового договора.
- Перехват трафика без согласия является нарушением законодательства РФ (ст. 138 УК РФ) и ряда других юрисдикций.
- Приватный ключ CA (
certs/ca.key) должен быть доступен только администратору — компрометация ключа позволяет подделывать любые сертификаты.
ssl-inspector/
├── cmd/
│ └── ssl-inspector/
│ └── main.go # CLI: gen-ca, start
├── internal/
│ ├── inspector/
│ │ ├── inspector.go # Ядро: MITM-прокси, перехват TLS
│ │ └── ca_gen.go # Генерация корневого CA
│ └── dashboard/
│ └── server.go # Веб-дашборд + REST API
├── certs/ # CA-сертификат и ключ (создаётся при gen-ca)
├── go.mod
└── docs/
└── README.md # Эта документация