feat: add anti-abuse mechanisms
Prevent slot blocking and reservation spam: - RateLimiter: per-sender cooldowns, hourly limits, pending caps - ProofOfWork: Hashcash-style PoW for reservation requests - SenderReputation: track honor rate, no-shows, auto-block - TherapistPolicy: configurable requirements per provider - 7 new tests (39 total) Docs: docs/anti-abuse.md with implementation roadmap
This commit is contained in:
216
docs/anti-abuse.md
Normal file
216
docs/anti-abuse.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# Anti-Abuse: Preventing Slot Blocking
|
||||
|
||||
## Problem
|
||||
|
||||
Bad actors could abuse the reservation system by:
|
||||
1. **Slot Squatting**: Reserving slots with no intention to attend
|
||||
2. **Denial of Service**: Mass-reserving to block legitimate patients
|
||||
3. **Competitor Sabotage**: Blocking a therapist's calendar
|
||||
4. **Spam Queries**: Flooding the network with fake queries
|
||||
|
||||
## Defense Layers
|
||||
|
||||
### Layer 1: Rate Limiting (Protocol Level)
|
||||
|
||||
```rust
|
||||
pub struct RateLimits {
|
||||
/// Max reservations per sender per hour
|
||||
pub max_reservations_per_hour: u8, // Default: 3
|
||||
/// Max pending (unconfirmed) reservations per sender
|
||||
pub max_pending_reservations: u8, // Default: 2
|
||||
/// Min time between reservations (seconds)
|
||||
pub reservation_cooldown_secs: u32, // Default: 300 (5 min)
|
||||
/// Max queries per sender per minute
|
||||
pub max_queries_per_minute: u8, // Default: 10
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**: Each relay tracks sender activity and drops excessive requests.
|
||||
|
||||
### Layer 2: Reservation Deposits (Economic)
|
||||
|
||||
Require a small proof-of-work or micro-deposit to make reservations:
|
||||
|
||||
| Method | Cost to Attacker | UX Impact |
|
||||
|--------|------------------|-----------|
|
||||
| **Hashcash PoW** | CPU time (~1-5s per reservation) | Slight delay |
|
||||
| **Token Stake** | Loses stake on no-show | Requires token system |
|
||||
| **Reputation Bond** | Loses reputation on abuse | Requires history |
|
||||
|
||||
**Recommended**: Start with Hashcash PoW — no external dependencies.
|
||||
|
||||
```rust
|
||||
pub struct ReservationProof {
|
||||
/// Hashcash proof-of-work (20-bit difficulty)
|
||||
pub pow_nonce: u64,
|
||||
/// Hash must start with N zero bits
|
||||
pub difficulty: u8,
|
||||
}
|
||||
|
||||
impl ReservationProof {
|
||||
pub fn verify(&self, reservation_id: &[u8; 16]) -> bool {
|
||||
let hash = sha256([reservation_id, &self.pow_nonce.to_le_bytes()].concat());
|
||||
leading_zeros(&hash) >= self.difficulty
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Layer 3: Confirmation Requirements
|
||||
|
||||
Therapists can require confirmation steps:
|
||||
|
||||
```rust
|
||||
pub enum ConfirmationMode {
|
||||
/// Auto-confirm (trust network)
|
||||
AutoConfirm,
|
||||
/// Require patient to solve CAPTCHA-like challenge
|
||||
ChallengeResponse { challenge: Vec<u8> },
|
||||
/// Require callback to verify contact
|
||||
ContactVerification { method: ContactMethod },
|
||||
/// Manual review by therapist
|
||||
ManualReview,
|
||||
}
|
||||
```
|
||||
|
||||
### Layer 4: No-Show Tracking
|
||||
|
||||
Track reservation outcomes per sender:
|
||||
|
||||
```rust
|
||||
pub struct SenderReputation {
|
||||
pub address: [u8; 16],
|
||||
pub reservations_made: u32,
|
||||
pub reservations_honored: u32,
|
||||
pub reservations_cancelled: u32, // With notice
|
||||
pub no_shows: u32, // Without notice
|
||||
pub last_no_show: Option<u64>,
|
||||
}
|
||||
|
||||
impl SenderReputation {
|
||||
pub fn honor_rate(&self) -> f32 {
|
||||
if self.reservations_made == 0 { return 0.5; }
|
||||
(self.reservations_honored as f32) / (self.reservations_made as f32)
|
||||
}
|
||||
|
||||
pub fn is_blocked(&self) -> bool {
|
||||
self.no_shows >= 3 || self.honor_rate() < 0.5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Therapists can share blocklists** via signed messages:
|
||||
|
||||
```rust
|
||||
pub struct BlocklistEntry {
|
||||
pub blocked_address: [u8; 16],
|
||||
pub reason: BlockReason,
|
||||
pub reported_by: [u8; 16],
|
||||
pub signature: [u8; 64],
|
||||
pub timestamp: u64,
|
||||
}
|
||||
|
||||
pub enum BlockReason {
|
||||
NoShow,
|
||||
Spam,
|
||||
Harassment,
|
||||
FakeIdentity,
|
||||
}
|
||||
```
|
||||
|
||||
### Layer 5: Reservation Limits per Therapist
|
||||
|
||||
Therapists set their own limits:
|
||||
|
||||
```rust
|
||||
pub struct TherapistPolicy {
|
||||
/// Max pending reservations from new senders
|
||||
pub max_pending_new: u8, // Default: 1
|
||||
/// Max pending from established senders
|
||||
pub max_pending_established: u8, // Default: 3
|
||||
/// Require verification level for reservations
|
||||
pub min_verification_level: u8, // 0 = any, 2 = peer-endorsed
|
||||
/// Auto-reject senders with low honor rate
|
||||
pub min_honor_rate: f32, // Default: 0.7
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Roadmap
|
||||
|
||||
### Phase 1: Basic Rate Limiting (Week 1)
|
||||
- [ ] Add `RateLimiter` to `ServiceRouter`
|
||||
- [ ] Track per-sender reservation counts
|
||||
- [ ] Drop excessive requests with `ServiceAction::RateLimited`
|
||||
|
||||
### Phase 2: Proof-of-Work (Week 2)
|
||||
- [ ] Add `ReservationProof` to reserve message payload
|
||||
- [ ] Verify PoW before processing reservation
|
||||
- [ ] Adaptive difficulty based on network load
|
||||
|
||||
### Phase 3: Reputation System (Week 3-4)
|
||||
- [ ] `SenderReputation` storage
|
||||
- [ ] Honor/no-show reporting from therapists
|
||||
- [ ] Blocklist propagation
|
||||
|
||||
### Phase 4: Therapist Policies (Week 4+)
|
||||
- [ ] Policy field in `SlotAnnounce`
|
||||
- [ ] Policy enforcement in reservation handling
|
||||
|
||||
## Example: Complete Anti-Abuse Flow
|
||||
|
||||
```
|
||||
Patient Relay Therapist
|
||||
| | |
|
||||
|-- Query (CBT, 104xx) -->| |
|
||||
|<-- Matches (3 slots) ---| |
|
||||
| | |
|
||||
|-- Reserve (slot_id) --->| |
|
||||
| + PoW proof | |
|
||||
| (1.2s computation) | |
|
||||
| |-- Check rate limit ------>|
|
||||
| | (OK: 1st today) |
|
||||
| |-- Check reputation ------>|
|
||||
| | (OK: new sender, 0.5) |
|
||||
| |-- Forward reserve ------->|
|
||||
| | |
|
||||
| |<-- Confirm (pending) -----|
|
||||
|<-- Pending -------------| |
|
||||
| | |
|
||||
| [Patient attends] | |
|
||||
| |<-- Outcome: honored ------|
|
||||
| | (reputation += 1) |
|
||||
```
|
||||
|
||||
## Edge Cases
|
||||
|
||||
### New Users (No History)
|
||||
|
||||
- Allow 1 pending reservation
|
||||
- Require PoW
|
||||
- Lower priority than established users
|
||||
|
||||
### Therapist Gaming the System
|
||||
|
||||
- Therapists could falsely report no-shows
|
||||
- Mitigation: Require mutual confirmation (patient confirms attendance too)
|
||||
- Weight reports by reporter reputation
|
||||
|
||||
### Sybil Attacks (Many Fake Identities)
|
||||
|
||||
- Each identity requires new Ed25519 keypair
|
||||
- PoW per reservation makes mass-blocking expensive
|
||||
- Cross-relay blocklist sharing limits damage
|
||||
|
||||
## Privacy Considerations
|
||||
|
||||
- Reputation is tied to mesh address, not real identity
|
||||
- No-show reports don't reveal appointment details
|
||||
- Blocklists only contain addresses + reason, not personal data
|
||||
|
||||
## Metrics to Monitor
|
||||
|
||||
| Metric | Healthy Range | Alert Threshold |
|
||||
|--------|---------------|-----------------|
|
||||
| Reservation/Confirm ratio | > 0.8 | < 0.5 |
|
||||
| Unique senders per relay | Growing | Flat with high volume |
|
||||
| PoW rejection rate | < 5% | > 20% |
|
||||
| Blocklist growth | Slow | Rapid spike |
|
||||
Reference in New Issue
Block a user