Skip to content

microscaler/fleetingdns

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

154 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌐 Fleeting DNS Forwarder (FDF)

Instant, Secure, and Temporary DNS Endpoints for Development & Testing

Project status (2026-07): working prototype. The core data plane β€” DNS, SNI-routed edge, SSH reverse tunnels (tcpip-forward/forwarded-tcpip), Redis slot allocation, TTL teardown β€” is implemented and covered by an integration suite. Items marked (planned) below are not yet shipped. Authoritative story status: docs/engineering/stories_detailed/E2_E3_tunnel_data_plane_user_stories_v0.3.md. Naming note: older diagrams use the legacy edf.run domain; the public domain is fleetingdns.run.


πŸš€ What is FleetingDNS?

FleetingDNS is a secure, easy-to-use service that provides temporary, publicly accessible DNS endpoints, instantly forwarding traffic to your local machine or continuous integration (CI) environment. Built specifically for developers and CI pipelines, it solves common problems faced during testing, including external integrations such as webhooks, OAuth callbacks, and multi-tenant application routing.


πŸ› οΈ Why Do Developers Need FDF?

Developers frequently face challenges when testing systems that require external services:

  • OAuth flows: Need public URLs for callback validations.
  • Webhooks: Services like Stripe, GitHub, or Slack need publicly accessible endpoints.
  • Integration Tests: Require realistic public DNS scenarios.
  • Multi-tenant Applications: Need separate subdomains to replicate production routing and authentication.

Using localhost or editing local DNS entries (/etc/hosts) is cumbersome and doesn't replicate real-world scenarios accurately.


FDF resolves these pain points by creating secure, ephemeral, and publicly resolvable DNS endpoints that seamlessly route traffic back to your local development or CI environment.

  • a developer is on a hotel Wi-Fi behind NAT + firewall,
  • a GitHub Actions job provisions an EDF endpoint, and
  • Stripe fires real web-hooks at that endpoint.
flowchart TD
    %% Actors
    subgraph Hotel_Network["Hotel Wi-Fi / NAT πŸ”’"]
        DevLaptop["πŸ–₯️ Developer laptop <br/> edf forward --port 3000"]
    end

    subgraph GitHub_Cloud["GitHub Actions"]
        GHRunner["CI Runner<br/>epdns-action"]
    end

    subgraph EDF_Cloud["FleetingDNS (multi-PoP)"]
        API["EDF API + CA<br/>(issue short-lived cert)"]
        Redis[(πŸ”— Redis slot+meta cache)]
        EdgeHub["Edge + Hub<br/>(rustls mTLS, Trust-DNS)"]
        DNSAuth["Stateless / Redis DNS"]
    end

    Stripe["🌐 Stripe Webhook Service"]

    %% Provisioning / control plane
    GHRunner -- "1️⃣ REST ➜ create endpoint<br/>(return FQDN + cert)" --> API
    DevLaptop -- "2️⃣ Outbound mTLS tunnel<br/>(cert from API)" --> EdgeHub
    EdgeHub -- "3️⃣ SET slotβ†’tcp in Redis" --> Redis
    API -- "3b️⃣ DNS label (stateless)<br/>TTL 30 s" --> DNSAuth

    %% Web-hook data plane
    Stripe -- "4️⃣ POST https://<label>.edf.run/<br/>(webhook payload)" --> DNSAuth
    DNSAuth -- "A-record lookup" --> EdgeHub
    Stripe ---> EdgeHub
    EdgeHub -- "5️⃣ forward over tunnel" --> DevLaptop
    DevLaptop -- "6️⃣ 200 OK" --> EdgeHub
    EdgeHub --> Stripe

    %% Return path for CI logs
    DevLaptop -- "Test assertions / logs" --> GHRunner
Loading

Flow summary

  1. CI runner calls the EDF API to create an endpoint; API signs a 30-minute client certificate and returns the generated FQDN.
  2. Developer laptop (inside hotel NAT) opens an outbound SSH reverse tunnel to the nearest EDF Edge + Hub node (mTLS wrapping of this transport is planned).
  3. The hub stores the new slot β†’ TCP stream mapping in Redis; the API has already made the stateless DNS label live.
  4. Stripe resolves the FQDN, gets the hub anycast IP, and sends the webhook.
  5. The hub validates the label, looks up the slot, and pipes the HTTP request through the encrypted tunnel to the developer’s localhost.
  6. The laptop’s app returns 200 OK; the response propagates back to Stripe, and the CI job can read test results.

βœ… Key Features

  • Instant DNS Creation: Generate temporary endpoints instantly from the command line.
  • Automatic Cleanup: Endpoints self-destruct after their set TTL (time-to-live).
  • TLS at the Edge: Public HTTPS terminated at the edge with SNI-based routing; per-session ephemeral certificates on the tunnel transport (planned β€” tunnel is currently plain SSH).
  • Protected Tunnels: Session-grant cookie gating on protected endpoints; API auth via Basic/HMAC/OIDC.
  • Easy Integration: SDKs for Python, JavaScript, and Go (planned).
  • CI/CD Ready: GitHub Actions integration (planned).
  • Customizable Plans: Stripe-powered payment tiers (planned β€” service-plan and billing models exist; Stripe not yet wired).

πŸ” When Should You Use FDF?

  • Testing OAuth and OpenID Connect flows locally or in CI.
  • Validating external webhook integrations (Stripe, GitHub, Twilio).
  • Running integration tests that require public DNS entries.
  • Simulating multi-tenant routing (host-header-based routing).
  • Debugging scenarios that require realistic public network environments.

πŸ§‘β€πŸ’» Example Scenario: Stripe Webhook Integration

Traditional testing requires exposing a local port publicly or deploying test instances, both tedious and insecure.

With FDF:

fleetingdns forward --port 3000 --ttl 1800

This command instantly creates a public DNS endpoint (e.g., https://abc123.fleetingdns.run) that Stripe can use to send webhook events directly to your locally running test server. FDF handles the routing securely, and after 30 minutes, the endpoint and tunnel close automatically.


The use-case diagrams below show the target architecture. Divergences today: the tunnel transport is plain SSH (TLS wrapping planned), OAuth/cert-based client auth is not yet enforced, and wildcard multi-tenant subdomains are planned.

βœ… Use Case: Developer Using FDF to Test a Webhook

sequenceDiagram
  autonumber
  participant Dev as Developer (CLI)
  participant API as FDF API
  participant CA as FDF CA & Auth
  participant Hub as Tunnel Gateway
  participant Edge as HTTPS Endpoint
  participant Webhook as Webhook Provider (e.g., Stripe)
  participant App as Local Dev Server

  Dev->>Dev: Start dev server (localhost:3000)
  Dev->>Dev: Run `edf forward --port 3000`
  Dev->>API: Authenticate via OAuth or API token
  API->>CA: Request ephemeral TLS cert (30m expiry)
  CA-->>API: Signed TLS certificate (PEM)
  API-->>Dev: Endpoint metadata + signed cert (in-memory only)

  Dev->>Hub: TLS+SSH tunnel initiated using client cert
  Hub-->>Dev: Reverse port bound (e.g. slot 60001)
  API->>Edge: Create DNS A record (e.g. abc123.edf.run β†’ Edge)

  Note over Dev,Edge: βœ… Developer sees live public HTTPS URL

  Dev->>Webhook: Register webhook with public URL (e.g. https://abc123.edf.run/webhook)

  Webhook->>Edge: Send event to public DNS endpoint
  Edge->>Hub: Resolve slot for abc123.edf.run
  Hub->>Dev: Forward POST /webhook through tunnel
  Dev->>App: Inject POST /webhook β†’ localhost:3000
  App-->>Dev: 200 OK
  Dev-->>Hub: Response back through tunnel
  Hub-->>Edge: Return 200 OK to webhook provider
  Edge-->>Webhook: Acknowledge webhook

  Note over Dev: πŸ” CLI shows: β€œWebhook received – 200 OK”

  alt TTL expires or Dev presses Ctrl+C
    Dev->>API: Delete endpoint
    API->>Hub: Close tunnel
    API->>Edge: Remove DNS record
  end
Loading

βœ… Use Case: Developer Testing OAuth Login Flow Locally

sequenceDiagram
  autonumber
  participant Dev as Developer (CLI)
  participant API as FDF API
  participant CA as FDF CA
  participant Hub as Tunnel Gateway
  participant Edge as HTTPS Endpoint
  participant Browser as Browser (User/Dev)
  participant IdP as OAuth Provider (Google, GitHub)
  participant App as Local Dev App

  Dev->>Dev: Start local app on http://localhost:3000
  Dev->>Dev: Run `edf forward --port 3000`
  Dev->>API: Authenticate + request cert
  API->>CA: Sign ephemeral cert (valid 30m)
  CA-->>API: Signed TLS cert
  API-->>Dev: Return fqdn + cert
  Dev->>Hub: Establish TLS-wrapped SSH tunnel
  API->>Edge: DNS β†’ abc123.edf.run β†’ Edge

  Dev->>IdP: Register OAuth app with redirect URI: https://abc123.edf.run/oauth/callback

  Browser->>App: Click β€œLogin with GitHub”
  App->>Browser: Redirect β†’ https://github.com/login/oauth/authorize?...&redirect_uri=https://abc123.edf.run/oauth/callback
  Browser->>IdP: Login and consent
  IdP->>Browser: Redirect to https://abc123.edf.run/oauth/callback?code=XYZ

  Browser->>Edge: GET /oauth/callback?code=XYZ
  Edge->>Hub: Route to slot abc123
  Hub->>Dev: Forward request via tunnel
  Dev->>App: GET /oauth/callback?code=XYZ β†’ localhost:3000
  App->>IdP: Exchange code for token
  IdP-->>App: Access token response
  App->>Browser: Respond with 200 OK / redirect to dashboard

  Note over Dev: πŸ”’ OAuth callback tested securely & end-to-end
Loading

βœ… Use Case: Multi-Tenant App Routing with Subdomain Matching

sequenceDiagram
  autonumber
  participant Dev as Developer (CLI)
  participant API as FDF API
  participant CA as FDF CA
  participant Hub as Tunnel Gateway
  participant Edge as HTTPS Endpoint
  participant Browser as QA/User
  participant App as Local Dev App

  Dev->>Dev: Start multi-tenant app on localhost:3000
  Dev->>Dev: Run `edf forward --port 3000 --subdomain myapp`
  Dev->>API: Authenticate + request cert for *.myapp.edf.run
  API->>CA: Sign wildcard cert
  CA-->>API: Cert for *.myapp.edf.run
  API-->>Dev: fqdn: tenantA.myapp.edf.run, cert, TTL
  Dev->>Hub: Connect reverse tunnel using wildcard cert
  API->>Edge: Create wildcard DNS entries

  Note over Dev,Edge: 🌐 Now routing *.myapp.edf.run β†’ tunnel

  Browser->>Edge: GET https://tenantA.myapp.edf.run
  Edge->>Hub: Lookup tunnel for *.myapp.edf.run
  Hub->>Dev: Forward to local tunnel
  Dev->>App: Host header = tenantA.myapp.edf.run
  App-->>Dev: Render tenantA dashboard
  Dev-->>Browser: HTML response via tunnel

  Note over App: 🏷️ App routes by Host header to tenant-specific logic
Loading

🧭 What It Shows

This diagram represents the normal β€œhappy path” flow for a developer:

  • Starts a local app
  • Opens a secure, time-limited public endpoint
  • Tests an integration (e.g. a webhook or OAuth redirect)
  • Tunnels are secure and isolated per session
  • DNS and tunnel clean up automatically when done

πŸ“š Documentation and SDKs

(planned) SDKs for Python, JavaScript/TypeScript, Go, Java, Kotlin, C#, Ruby, Swift, and Rust are on the roadmap; none are published yet. This repository contains the Rust backend and the fleetingdns CLI. Engineering documentation lives in docs/engineering/.


πŸ”’ Security First

Shipped today:

  • Slot-allocation gate: only API-allocated tunnel slots can be bound on the hub (fail-closed against Redis).
  • Session-grant cookie gating for protected tunnels, verified at the edge before any bytes are forwarded.
  • TTL-based teardown of tunnels, slots, and DNS records; viewer-idle reaping for portal sessions.
  • API authentication (Basic, HMAC, OIDC) and rate limiting on the control plane.

Planned (not yet enforced β€” see stories TDP-12/TDP-13):

  • TLS-wrapped SSH tunnel transport with ephemeral per-session client certificates.
  • SSH key validation against API-issued keypairs (current dev builds accept any key).
  • Per-peer brute-force lockout on the SSH path.

🚧 GitHub Actions Integration (planned)

Intended usage once the action ships:

- uses: fleetingdns/fleetingdns-action@v1
  with:
    port: 3000
    ttl: 1200
    auth: true

🌟 Get Started Today

Hosted install script (planned). Today, build from source:

cargo build --release -p edf-cli

Prototype DNS Daemon

This repository includes a minimal DNS daemon for local testing. Start it with:

cargo run -p dnsd-bin

The service binds to 0.0.0.0:6353 by default and logs dnsd listening when ready.

Prototype 0.1

Spin up the proof-of-concept in three quick commands:

cargo run -p dnsd-bin
dig @127.0.0.1 -p6353 test.fdns.run +short

If everything is running correctly, the final command prints 127.0.0.1. A fresh machine should be able to run through the setup in under five minutes.

Docker Image

Build and run the daemon without Rust:

docker build -f docker/Dockerfile .
docker run --rm -p 53:53/udp -p 53:53/tcp <image-id>

Slot Setter

Populate Redis manually during development:

cargo run -p slot-setter demo 1.2.3.4 --ttl 600

This stores the IP 1.2.3.4 under the key demo with a 10 minute expiry.

EdgeHub

Run the tunnel hub (plain-SSH reverse-tunnel listener + SNI-routed HTTPS router):

cargo run -p edgehub-bin

The SSH listener binds to 0.0.0.0:2222 by default and logs edgehub listening on startup. TLS wrapping of the SSH transport is planned (see E2 design status banner).


Β© 2025 FleetingDNS