Skip to content

RFC-27: IP ownership verification for user connection (tracker) #4194

Description

@elitegreg

Tracking issue for implementing RFC-27 (rfcs/rfc27-ip-verification.md, added in #2304).

Why

create_user_core accepts any globally-routable client_ip when the AccessPass is a wildcard pass — stored at 0.0.0.0 or flagged allow_multiple_ip, which includes the EdgeSeat passes the shred-oracle issues. is_global() is the only check applied. That leaves two holes: squatting on the (client_ip, user_type) User PDA to lock out the legitimate operator, and pointing device tunnel/route provisioning at a third party's address.

RFC-27 closes them with a signed IpOwnershipProof from a DoubleZero-operated verification service, validated onchain through the Ed25519 precompile so it cannot be bypassed by calling the program directly.

Decisions made ahead of implementation

These resolve RFC open questions and the review points in #4192. The RFC text is amended to match as part of the onchain validation issue.

Question Decision
Replay binding Signed message is payer || client_ip || epoch || user_pubkey, with a domain-separation prefix and version byte. Binding the target User PDA stops a routine connect proof from being replayed into a destructive operation (see #4192 item 2 and the future ReclaimUser work in #4190).
Freshness window Accept clock.epoch and clock.epoch - 1. Fixed constant, not configurable.
Rollout FeatureFlag::RequireIpOwnershipProof (bit 2). Proof optional until the flag is set per environment, then required for every user creation — wildcard and specific-IP alike.
Persist proofs onchain No. The bound client_ip plus transaction history is the audit record.
IPv6 Out of scope. The program's client_ip surface is Ipv4Addr and the User PDA derives from it.
Periodic re-verification Out of scope here. Re-proving on a schedule and releasing a user whose IP changed hands is tracked in #4193 / #4190.
Key rotation Verifier pubkey lives in GlobalState and rotates through the existing SetAuthority instruction. No cadence set; rotation invalidates outstanding proofs and clients re-verify on next connect.

Work

Foundations:

Onchain enforcement:

Off-chain service:

Client path:

Ecosystem:

Ordering

#4195 and #4196 are independent and unblock everything. #4197 needs both. #4198 needs #4195. #4200 needs #4195 and #4197's argument shape. #4201 needs #4198 and #4200. #4203 needs #4196. #4204 needs #4198. #4205 needs #4197, #4201, and #4204. #4202 is independent and can land any time. #4225 needs #4197 and must land before require-ip-ownership-proof is set in any environment the device-stress orchestrator runs against.

Not in scope

Releasing or reclaiming a User account whose IP has changed hands (#4193, #4190), periodic re-verification, and IPv6.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions