montana/Русский/Совет/OpenAI/атака_затмения_07.01.2026_17:39.md

139 lines
7.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

**Модель:** GPT-5.2
**Компания:** OpenAI
**Дата:** 07.01.2026 17:39 UTC
---
## Eclipse Attack — оценка возможности в Montana
Источник требований: `Montana ACP/Council/PROMPT_COUNSIL_TEMPLATE.md` (вектор «Eclipse Attack»).
Код: `Montana ACP/montana/src/net/{protocol.rs,addrman.rs,connection.rs,eviction.rs}`.
---
## 1) Что требуется для eclipse по архитектуре
В Montana outbound-пиры выбираются из `AddrMan::select()` (50/50 NEW/TRIED). Это означает: если злоумышленник может сильно исказить содержимое `AddrMan` так, что большинство «доступных» кандидатов — его адреса, он повышает шанс, что после рестарта жертва поднимет outbound в основном к нему.
Факт выбора через AddrMan:
```500:555:/Users/kh./Python/ACP_1/Montana ACP/montana/src/net/protocol.rs
// Peer selection from AddrMan
let net_addr = {
let mut addrman = addresses.write().await;
match addrman.select() {
Some(addr) => addr,
None => continue,
}
};
...
// Check netgroup diversity
if !connections.can_connect(&socket_addr).await { continue; }
// Check per-IP limit
if !connections.can_accept_from_ip(&socket_addr).await { continue; }
```
---
## 2) Что защищает от классического «TRIED poisoning через fake TCP connect»
Критически важно: адрес переводится в TRIED только после завершения рукопожатия (`Version + Verack`), а не при одном TCP connect.
```944:953:/Users/kh./Python/ACP_1/Montana ACP/montana/src/net/protocol.rs
Message::Verack => {
peer.handshake_complete();
just_connected = true;
// Mark address as successfully connected (moves to TRIED table in AddrMan).
addresses.write().await.mark_connected(&peer.addr);
}
```
А `mark_connected()` двигает адрес в TRIED:
```342:346:/Users/kh./Python/ACP_1/Montana ACP/montana/src/net/addrman.rs
pub fn mark_connected(&mut self, addr: &SocketAddr) {
self.connected.insert(*addr);
self.mark_good(addr);
}
```
**Вывод:** самый простой вариант eclipse, когда достаточно «принять TCP» для продвижения в TRIED — в текущем коде закрыт.
---
## 3) Где остаётся возможность eclipse (при сильном противнике)
### 3.1 Poisoning NEW (ограниченно, но возможно)
`AddrMan::add()` кладёт адрес в NEW по бакету/позиции. При коллизии сохраняется «нетеррибл» запись.
```131:175:/Users/kh./Python/ACP_1/Montana ACP/montana/src/net/addrman.rs
if let Some(existing_idx) = self.new_table[idx] {
if let Some(existing) = self.addrs.get(&existing_idx)
&& !existing.is_terrible()
{
return false; // Keep existing good address
}
self.remove_from_new(existing_idx);
}
```
Это означает: если противник (1) способен сделать так, чтобы жертва приняла много routable/свежих адресов и (2) эти адреса не быстро становятся "terrible", то он может увеличивать долю своих адресов в NEW.
### 3.2 Barrier: netgroup diversity + per-IP limits
Outbound-кандидат проходит:
- `/16` netgroup limit (`MAX_PEERS_PER_NETGROUP=2`)
- per-IP limit (`MAX_CONNECTIONS_PER_IP=2`)
```48:53:/Users/kh./Python/ACP_1/Montana ACP/montana/src/net/types.rs
pub const MAX_CONNECTIONS_PER_IP: usize = 2;
```
```202:210:/Users/kh./Python/ACP_1/Montana ACP/montana/src/net/types.rs
pub const MAX_PEERS_PER_NETGROUP: usize = 2;
```
**Следствие:** eclipse становится практичным только для противника, который может предоставить много адресов в разных /16 (и не упереться в per-IP cap).
### 3.3 Отсутствие явных «anchor peers» на рестарт
Код явно сохраняет `addresses.dat` и затем снова делает выбор через `AddrMan::select()`; отдельного механизма закрепления (anchor) списка проверенных outbound-пиров в явном виде в `net/*` не видно.
Это делает «рестартный» аспект eclipse (из шаблона) релевантным: после рестарта жертва снова полагается на качество `AddrMan`.
---
## 4) Применимость eviction к eclipse
На inbound включена eviction-логика при достижении лимита.
```354:376:/Users/kh./Python/ACP_1/Montana ACP/montana/src/net/protocol.rs
if !connections.can_accept_inbound() {
let peer_infos: Vec<_> = peers.read().await.values()
.map(super::peer::PeerInfo::from)
.collect();
if let Some(evict_addr) = super::eviction::select_peer_to_evict(&peer_infos) {
...
connections.remove_peer(&evict_addr, true).await;
} else {
continue;
}
}
```
Это помогает против DoS/slot-grabbing, но eclipse по outbound всё равно определяется составом `AddrMan` и фильтрами отбора.
---
## 5) Итоговая оценка
- **«TRIED poisoning через fake TCP connect»**: в текущем коде **закрыто** (TRIED только после handshake).
- **Eclipse через «смещение AddrMan → перехват outbound после рестартов»**: **возможен при сильном противнике**, способном обеспечить широкую /16 диверсификацию и выдерживать per-IP ограничения.
---
## 6) Рекомендации (защитные)
- **Усилить критерий “good” для TRIED**: считать “good” не только handshake, а минимальный период корректного поведения/обслуживания запросов (anti-TRIED inflation).
- **Добавить явные “anchor peers”**: хранить небольшой набор проверенных outbound peers, которые переживают рестарт и подключаются приоритетно.
- **Интегрировать feeler**: `FeelerManager` существует, но в `net/*` не видно его использования в runtime; подключение feeler-валидации повышает качество NEW.
- **Перенести/добавить ограничения на приём Addr**: сейчас это per-peer; для анти-Sybil усилить per-IP/per-subnet учёт именно для addr-relay.