mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Improve README and enable DNS resolver by default
Rework top-level README: add badges, status/roadmap section, config search path docs, minimal two-node example with transports, DNS setup instructions with systemd-resolved and resolv.conf examples, and connectivity test walkthrough. Replace ASCII document-relationship diagram with SVG in design docs. Change DNS resolver default from disabled to enabled (port 5354). Update config merge to allow higher-priority configs to disable it.
This commit is contained in:
@@ -1,12 +1,16 @@
|
|||||||
# FIPS: Free Internetworking Peering System
|
# FIPS: Free Internetworking Peering System
|
||||||
|
|
||||||
|
[](LICENSE)
|
||||||
|
[](https://www.rust-lang.org/)
|
||||||
|
[-yellow.svg)](#status--roadmap)
|
||||||
|
|
||||||
A distributed, decentralized network routing protocol for mesh nodes
|
A distributed, decentralized network routing protocol for mesh nodes
|
||||||
connecting over arbitrary transports.
|
connecting over arbitrary transports.
|
||||||
|
|
||||||
> **Status: Experimental / Pre-release**
|
> **Status: Alpha (0.1.0)**
|
||||||
>
|
>
|
||||||
> FIPS is under active development. The protocol and APIs are not stable.
|
> FIPS is under active development. The protocol and APIs are not stable.
|
||||||
> Expect breaking changes.
|
> Expect breaking changes. See [Status & Roadmap](#status--roadmap) below.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -38,8 +42,8 @@ sessions across the mesh.
|
|||||||
measurement
|
measurement
|
||||||
- **Operator visibility** — `fipsctl` control socket interface for runtime
|
- **Operator visibility** — `fipsctl` control socket interface for runtime
|
||||||
inspection of peers, links, sessions, tree state, and metrics
|
inspection of peers, links, sessions, tree state, and metrics
|
||||||
- **Zero configuration** — sensible defaults; a node can run with no config
|
- **Zero configuration** — sensible defaults; a node can start with no config
|
||||||
file
|
file, though peer addresses are needed to join a network
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
@@ -59,16 +63,77 @@ cargo build --release
|
|||||||
### Run
|
### Run
|
||||||
|
|
||||||
```
|
```
|
||||||
# With default configuration (ephemeral identity, default ports):
|
# Start with default search paths (see below):
|
||||||
sudo ./target/release/fips
|
sudo ./target/release/fips
|
||||||
|
|
||||||
# With a configuration file:
|
# With an explicit configuration file:
|
||||||
sudo ./target/release/fips -c fips.yaml
|
sudo ./target/release/fips -c fips.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Without `-c`, the node searches for `fips.yaml` in these locations
|
||||||
|
(highest priority first, values from later files override earlier ones):
|
||||||
|
|
||||||
|
1. `./fips.yaml` (current directory)
|
||||||
|
2. `~/.config/fips/fips.yaml` (user config)
|
||||||
|
3. `/etc/fips/fips.yaml` (system)
|
||||||
|
|
||||||
|
If no config file is found, the node starts with defaults (ephemeral
|
||||||
|
identity, default ports, no peers).
|
||||||
|
|
||||||
|
A minimal two-node setup (each node points at the other):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# node-a.yaml # node-b.yaml
|
||||||
|
node: # node:
|
||||||
|
identity: # identity:
|
||||||
|
nsec: "nsec1aaa..." # nsec: "nsec1bbb..."
|
||||||
|
transports: # transports:
|
||||||
|
udp: # udp:
|
||||||
|
bind_addr: "0.0.0.0:4000" # bind_addr: "0.0.0.0:4000"
|
||||||
|
peers: # peers:
|
||||||
|
- npub: "npub1bbb..." # - npub: "npub1aaa..."
|
||||||
|
addresses: # addresses:
|
||||||
|
- transport: udp # - transport: udp
|
||||||
|
addr: "10.0.0.2:4000" # addr: "10.0.0.1:4000"
|
||||||
|
```
|
||||||
|
|
||||||
|
The `nsec` field accepts bech32 (`nsec1...`) or hex-encoded secret keys.
|
||||||
|
Omit it entirely for an ephemeral identity that changes each restart.
|
||||||
|
|
||||||
See [docs/design/fips-configuration.md](docs/design/fips-configuration.md) for
|
See [docs/design/fips-configuration.md](docs/design/fips-configuration.md) for
|
||||||
the full configuration reference.
|
the full configuration reference.
|
||||||
|
|
||||||
|
### Test Connectivity
|
||||||
|
|
||||||
|
FIPS includes a built-in DNS resolver (enabled by default, port 5354)
|
||||||
|
that maps `.fips` names to fd00::/8 IPv6 addresses derived from each
|
||||||
|
node's public key. Configure your system to send `.fips` queries to it.
|
||||||
|
|
||||||
|
With systemd-resolved:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo resolvectl dns fips0 127.0.0.1:5354
|
||||||
|
sudo resolvectl domain fips0 ~fips
|
||||||
|
```
|
||||||
|
|
||||||
|
Or manually in `/etc/resolv.conf` (routes all DNS through FIPS for
|
||||||
|
`.fips` names only if your resolver supports conditional forwarding;
|
||||||
|
otherwise this sets it as a general nameserver):
|
||||||
|
|
||||||
|
```
|
||||||
|
nameserver 127.0.0.1
|
||||||
|
options port:5354
|
||||||
|
```
|
||||||
|
|
||||||
|
Once DNS is configured, ping a peer by npub:
|
||||||
|
|
||||||
|
```
|
||||||
|
ping6 npub1bbb....fips
|
||||||
|
```
|
||||||
|
|
||||||
|
Any IPv6-capable application can reach FIPS nodes this way — `ping6`,
|
||||||
|
`ssh`, `curl`, etc.
|
||||||
|
|
||||||
### Inspect
|
### Inspect
|
||||||
|
|
||||||
While a node is running, use `fipsctl` to inspect its state:
|
While a node is running, use `fipsctl` to inspect its state:
|
||||||
@@ -108,9 +173,37 @@ a layered protocol specification. Start with
|
|||||||
src/ Rust source (library + fips/fipsctl binaries)
|
src/ Rust source (library + fips/fipsctl binaries)
|
||||||
docs/design/ Protocol design specifications
|
docs/design/ Protocol design specifications
|
||||||
testing/ Docker-based integration test harnesses
|
testing/ Docker-based integration test harnesses
|
||||||
benches/ Criterion benchmarks
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Status & Roadmap
|
||||||
|
|
||||||
|
FIPS is at **v0.1.0 (alpha)**. The core protocol works end-to-end over
|
||||||
|
UDP/IP overlays but has not been tested beyond small meshes.
|
||||||
|
|
||||||
|
### What works today
|
||||||
|
|
||||||
|
- Spanning tree construction with greedy coordinate routing
|
||||||
|
- Bloom filter discovery for finding nodes without global state
|
||||||
|
- Noise IK (link layer) and Noise XK (session layer) encryption
|
||||||
|
- IPv6 TUN adapter with DNS resolution of `.fips` names
|
||||||
|
- Per-link metrics (RTT, loss, jitter, goodput)
|
||||||
|
- Runtime inspection via `fipsctl`
|
||||||
|
- Docker-based integration and chaos testing
|
||||||
|
|
||||||
|
### Near-term priorities
|
||||||
|
|
||||||
|
- Peer discovery via Nostr relays (bootstrap without static peer lists)
|
||||||
|
- Additional transports (Ethernet, Tor)
|
||||||
|
- Improved routing resilience under churn
|
||||||
|
- Security audit of cryptographic protocols
|
||||||
|
- CI pipeline and published crate
|
||||||
|
|
||||||
|
### Longer-term
|
||||||
|
|
||||||
|
- Mobile platform support
|
||||||
|
- Bandwidth-aware routing and QoS
|
||||||
|
- Protocol stability and versioned wire format
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT — see [LICENSE](LICENSE).
|
MIT — see [LICENSE](LICENSE).
|
||||||
|
|||||||
+1
-24
@@ -48,27 +48,4 @@ specific topics.
|
|||||||
|
|
||||||
## Document Relationships
|
## Document Relationships
|
||||||
|
|
||||||
```text
|

|
||||||
fips-intro.md
|
|
||||||
│
|
|
||||||
┌──────────────┼──────────────┐
|
|
||||||
▼ ▼ │
|
|
||||||
fips-transport-layer fips-mesh- │
|
|
||||||
│ operation │
|
|
||||||
▼ │ │
|
|
||||||
fips-mesh-layer ◄────────┤ │
|
|
||||||
│ │ │
|
|
||||||
▼ ├──► fips-spanning-tree
|
|
||||||
fips-session-layer │ │
|
|
||||||
│ └──► fips-bloom-filters
|
|
||||||
▼
|
|
||||||
fips-ipv6-adapter
|
|
||||||
fips-wire-formats
|
|
||||||
(referenced by all layer docs)
|
|
||||||
|
|
||||||
fips-configuration
|
|
||||||
(standalone reference)
|
|
||||||
|
|
||||||
spanning-tree-dynamics
|
|
||||||
(pedagogical companion to fips-spanning-tree)
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 520" font-family="system-ui, -apple-system, sans-serif" font-size="13">
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
|
||||||
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#555"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Background -->
|
||||||
|
<rect width="720" height="520" rx="8" fill="#fafafa" stroke="#ddd" stroke-width="1"/>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<text x="360" y="32" text-anchor="middle" font-size="16" font-weight="600" fill="#333">Document Relationships</text>
|
||||||
|
|
||||||
|
<!-- fips-intro -->
|
||||||
|
<rect x="260" y="50" width="200" height="32" rx="6" fill="#e3f2fd" stroke="#90caf9"/>
|
||||||
|
<text x="360" y="71" text-anchor="middle" font-weight="500" fill="#1565c0">fips-intro.md</text>
|
||||||
|
|
||||||
|
<!-- Arrows from intro -->
|
||||||
|
<line x1="310" y1="82" x2="130" y2="120" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
<line x1="360" y1="82" x2="360" y2="120" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- fips-transport-layer -->
|
||||||
|
<rect x="30" y="120" width="200" height="32" rx="6" fill="#e8f5e9" stroke="#a5d6a7"/>
|
||||||
|
<text x="130" y="141" text-anchor="middle" font-weight="500" fill="#2e7d32">fips-transport-layer.md</text>
|
||||||
|
|
||||||
|
<!-- fips-mesh-operation -->
|
||||||
|
<rect x="270" y="120" width="200" height="32" rx="6" fill="#fff3e0" stroke="#ffcc80"/>
|
||||||
|
<text x="370" y="141" text-anchor="middle" font-weight="500" fill="#e65100">fips-mesh-operation.md</text>
|
||||||
|
|
||||||
|
<!-- Arrow: transport -> mesh-layer -->
|
||||||
|
<line x1="130" y1="152" x2="130" y2="190" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- fips-mesh-layer -->
|
||||||
|
<rect x="30" y="190" width="200" height="32" rx="6" fill="#e8f5e9" stroke="#a5d6a7"/>
|
||||||
|
<text x="130" y="211" text-anchor="middle" font-weight="500" fill="#2e7d32">fips-mesh-layer.md</text>
|
||||||
|
|
||||||
|
<!-- Arrow: mesh-operation -> mesh-layer -->
|
||||||
|
<line x1="270" y1="145" x2="230" y2="200" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- Arrow: mesh-layer -> session-layer -->
|
||||||
|
<line x1="130" y1="222" x2="130" y2="260" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- fips-session-layer -->
|
||||||
|
<rect x="30" y="260" width="200" height="32" rx="6" fill="#e8f5e9" stroke="#a5d6a7"/>
|
||||||
|
<text x="130" y="281" text-anchor="middle" font-weight="500" fill="#2e7d32">fips-session-layer.md</text>
|
||||||
|
|
||||||
|
<!-- Arrow: session-layer -> ipv6-adapter -->
|
||||||
|
<line x1="130" y1="292" x2="130" y2="330" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- fips-ipv6-adapter -->
|
||||||
|
<rect x="30" y="330" width="200" height="32" rx="6" fill="#e8f5e9" stroke="#a5d6a7"/>
|
||||||
|
<text x="130" y="351" text-anchor="middle" font-weight="500" fill="#2e7d32">fips-ipv6-adapter.md</text>
|
||||||
|
|
||||||
|
<!-- Arrow: mesh-operation -> spanning-tree -->
|
||||||
|
<line x1="470" y1="145" x2="550" y2="190" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- Arrow: mesh-operation -> bloom-filters -->
|
||||||
|
<line x1="470" y1="148" x2="550" y2="260" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- fips-spanning-tree -->
|
||||||
|
<rect x="500" y="190" width="200" height="32" rx="6" fill="#f3e5f5" stroke="#ce93d8"/>
|
||||||
|
<text x="600" y="211" text-anchor="middle" font-weight="500" fill="#7b1fa2">fips-spanning-tree.md</text>
|
||||||
|
|
||||||
|
<!-- Arrow: intro -> spanning-tree -->
|
||||||
|
<line x1="460" y1="72" x2="560" y2="190" stroke="#555" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- fips-bloom-filters -->
|
||||||
|
<rect x="500" y="260" width="200" height="32" rx="6" fill="#f3e5f5" stroke="#ce93d8"/>
|
||||||
|
<text x="600" y="281" text-anchor="middle" font-weight="500" fill="#7b1fa2">fips-bloom-filters.md</text>
|
||||||
|
|
||||||
|
<!-- Arrow: spanning-tree -> bloom (dependency) -->
|
||||||
|
<line x1="600" y1="222" x2="600" y2="260" stroke="#999" stroke-dasharray="4,3" marker-end="url(#arrow)"/>
|
||||||
|
|
||||||
|
<!-- fips-wire-formats -->
|
||||||
|
<rect x="260" y="400" width="200" height="32" rx="6" fill="#fce4ec" stroke="#ef9a9a"/>
|
||||||
|
<text x="360" y="421" text-anchor="middle" font-weight="500" fill="#c62828">fips-wire-formats.md</text>
|
||||||
|
<text x="360" y="448" text-anchor="middle" font-size="11" fill="#888">(referenced by all layer docs)</text>
|
||||||
|
|
||||||
|
<!-- fips-configuration -->
|
||||||
|
<rect x="30" y="400" width="200" height="32" rx="6" fill="#f5f5f5" stroke="#bdbdbd"/>
|
||||||
|
<text x="130" y="421" text-anchor="middle" font-weight="500" fill="#424242">fips-configuration.md</text>
|
||||||
|
<text x="130" y="448" text-anchor="middle" font-size="11" fill="#888">(standalone reference)</text>
|
||||||
|
|
||||||
|
<!-- spanning-tree-dynamics -->
|
||||||
|
<rect x="500" y="330" width="200" height="32" rx="6" fill="#f3e5f5" stroke="#ce93d8"/>
|
||||||
|
<text x="600" y="351" text-anchor="middle" font-weight="500" fill="#7b1fa2">spanning-tree-dynamics.md</text>
|
||||||
|
<text x="600" y="378" text-anchor="middle" font-size="11" fill="#888">(companion to fips-spanning-tree)</text>
|
||||||
|
|
||||||
|
<!-- Legend -->
|
||||||
|
<rect x="30" y="472" width="14" height="14" rx="3" fill="#e8f5e9" stroke="#a5d6a7"/>
|
||||||
|
<text x="50" y="484" font-size="11" fill="#666">Protocol stack</text>
|
||||||
|
<rect x="155" y="472" width="14" height="14" rx="3" fill="#fff3e0" stroke="#ffcc80"/>
|
||||||
|
<text x="175" y="484" font-size="11" fill="#666">Mesh behavior</text>
|
||||||
|
<rect x="295" y="472" width="14" height="14" rx="3" fill="#f3e5f5" stroke="#ce93d8"/>
|
||||||
|
<text x="315" y="484" font-size="11" fill="#666">Supporting references</text>
|
||||||
|
<rect x="460" y="472" width="14" height="14" rx="3" fill="#fce4ec" stroke="#ef9a9a"/>
|
||||||
|
<text x="480" y="484" font-size="11" fill="#666">Wire formats</text>
|
||||||
|
<rect x="580" y="472" width="14" height="14" rx="3" fill="#f5f5f5" stroke="#bdbdbd"/>
|
||||||
|
<text x="600" y="484" font-size="11" fill="#666">Implementation</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.4 KiB |
@@ -229,7 +229,7 @@ with the node for routing.
|
|||||||
|
|
||||||
| Parameter | Type | Default | Description |
|
| Parameter | Type | Default | Description |
|
||||||
|-----------|------|---------|-------------|
|
|-----------|------|---------|-------------|
|
||||||
| `dns.enabled` | bool | `false` | Enable DNS responder |
|
| `dns.enabled` | bool | `true` | Enable DNS responder |
|
||||||
| `dns.bind_addr` | string | `"127.0.0.1"` | Bind address |
|
| `dns.bind_addr` | string | `"127.0.0.1"` | Bind address |
|
||||||
| `dns.port` | u16 | `5354` | Listen port |
|
| `dns.port` | u16 | `5354` | Listen port |
|
||||||
| `dns.ttl` | u32 | `300` | AAAA record TTL in seconds |
|
| `dns.ttl` | u32 | `300` | AAAA record TTL in seconds |
|
||||||
@@ -387,7 +387,7 @@ tun:
|
|||||||
mtu: 1280
|
mtu: 1280
|
||||||
|
|
||||||
dns:
|
dns:
|
||||||
enabled: false
|
enabled: true
|
||||||
bind_addr: "127.0.0.1"
|
bind_addr: "127.0.0.1"
|
||||||
port: 5354
|
port: 5354
|
||||||
ttl: 300
|
ttl: 300
|
||||||
|
|||||||
+2
-4
@@ -186,10 +186,8 @@ impl Config {
|
|||||||
if other.tun.mtu.is_some() {
|
if other.tun.mtu.is_some() {
|
||||||
self.tun.mtu = other.tun.mtu;
|
self.tun.mtu = other.tun.mtu;
|
||||||
}
|
}
|
||||||
// Merge dns section
|
// Merge dns section — higher-priority config always wins for enabled
|
||||||
if other.dns.enabled {
|
self.dns.enabled = other.dns.enabled;
|
||||||
self.dns.enabled = true;
|
|
||||||
}
|
|
||||||
if other.dns.bind_addr.is_some() {
|
if other.dns.bind_addr.is_some() {
|
||||||
self.dns.bind_addr = other.dns.bind_addr;
|
self.dns.bind_addr = other.dns.bind_addr;
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-3
@@ -20,11 +20,15 @@ const DEFAULT_DNS_PORT: u16 = 5354;
|
|||||||
/// Default DNS record TTL in seconds (5 minutes).
|
/// Default DNS record TTL in seconds (5 minutes).
|
||||||
const DEFAULT_DNS_TTL: u32 = 300;
|
const DEFAULT_DNS_TTL: u32 = 300;
|
||||||
|
|
||||||
|
fn default_true() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// DNS responder configuration (`dns.*`).
|
/// DNS responder configuration (`dns.*`).
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct DnsConfig {
|
pub struct DnsConfig {
|
||||||
/// Enable DNS responder (`dns.enabled`).
|
/// Enable DNS responder (`dns.enabled`, default: true).
|
||||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
#[serde(default = "default_true")]
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
|
|
||||||
/// Bind address (`dns.bind_addr`).
|
/// Bind address (`dns.bind_addr`).
|
||||||
@@ -40,6 +44,17 @@ pub struct DnsConfig {
|
|||||||
pub ttl: Option<u32>,
|
pub ttl: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for DnsConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: true,
|
||||||
|
bind_addr: None,
|
||||||
|
port: None,
|
||||||
|
ttl: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl DnsConfig {
|
impl DnsConfig {
|
||||||
/// Get the bind address (default: 127.0.0.1).
|
/// Get the bind address (default: 127.0.0.1).
|
||||||
pub fn bind_addr(&self) -> &str {
|
pub fn bind_addr(&self) -> &str {
|
||||||
|
|||||||
Reference in New Issue
Block a user