# plcdns **PLC Directory over DNS** - A DNS server that resolves Bluesky/AT Protocol DID PLC identifiers to their associated metadata via DNS TXT records. ## Features - 🔍 **Handle Resolution** - Resolve DIDs to their AT Protocol handles - 🌐 **PDS Discovery** - Find Personal Data Server endpoints - 🔧 **Service Resolution** - Resolve any service from DID documents (PDS, labelers, etc.) - 🔑 **Public Key Lookup** - Retrieve verification public keys - ⚡ **Caching** - 5-minute cache to reduce PLC directory load - 🐳 **Docker Support** - Easy deployment with Docker - ✅ **Comprehensive Tests** - Full test coverage ## Installation ### From Source ```bash # Clone the repository git clone https://tangled.org/@tree.fail/plcdns cd plcdns # Install dependencies go mod download # Build go build -o plcdns # Run ./plcdns -port 8053 ``` ### Using Docker ```bash # Build docker build -t plcdns . # Run docker run -p 8053:8053 -e DNS_PORT=8053 plcdns ``` ### Using Go Install ```bash go install tangled.org/@tree.fail/plcdns@latest ``` ## Usage ### Starting the Server ```bash # Default port (8053) ./plcdns # Custom port via flag ./plcdns -port 9053 # Custom port via environment variable DNS_PORT=9053 ./plcdns # Custom PLC directory ./plcdns -port 8053 -plc https://plc.directory ``` ### Query Formats The server supports four types of queries using different subdomain prefixes: | Query Type | Format | Returns | Example | |:-----------|:-------|:--------|:--------| | Handle | `_handle..plc.atscan.net` | AT Protocol handle | `test.bsky.social` | | PDS | `_pds..plc.atscan.net` | PDS endpoint URL | `https://bsky.social` | | Labeler | `_labeler..plc.atscan.net` | Labeler service URL | `https://mod.bsky.app` | | Public Key | `_pubkey..plc.atscan.net` | Public key (multibase) | `zQ3sh...` | ### Query Examples ```bash # Using dig dig @localhost -p 8053 _handle.z72i7hdynmk6r22z27h6tvur.plc.atscan.net TXT dig @localhost -p 8053 _pds.z72i7hdynmk6r22z27h6tvur.plc.atscan.net TXT dig @localhost -p 8053 _labeler.ar7c4by46qjdydhdevvrndac.plc.atscan.net TXT dig @localhost -p 8053 _pubkey.z72i7hdynmk6r22z27h6tvur.plc.atscan.net TXT # Using nslookup nslookup -type=TXT _handle.z72i7hdynmk6r22z27h6tvur.plc.atscan.net localhost -port=8053 # Using host host -t TXT _pds.z72i7hdynmk6r22z27h6tvur.plc.atscan.net localhost -p 8053 ``` ### Example Response ```bash $ dig @localhost -p 8053 _handle.z72i7hdynmk6r22z27h6tvur.plc.atscan.net TXT +short "bsky.app" $ dig @localhost -p 8053 _pds.z72i7hdynmk6r22z27h6tvur.plc.atscan.net TXT +short "https://bsky.social" ``` ## Configuration ### Command Line Flags | Flag | Default | Description | |:-----|:--------|:------------| | `-port` | `8053` | DNS server port | | `-plc` | `https://plc.directory` | PLC directory URL | ### Environment Variables | Variable | Description | |:---------|:------------| | `DNS_PORT` | Override default port (8053) | ### Cache Settings - **TTL**: 300 seconds (5 minutes) for DNS records - **Cache Duration**: 5 minutes for DID documents - **Cache Type**: In-memory map ## Testing ```bash # Run all tests go test -v # Run with coverage go test -v -cover # Generate coverage report go test -coverprofile=coverage.out go tool cover -html=coverage.out # Run with race detector go test -v -race ``` ## API Reference ### DID Document Structure The server fetches DID documents from the PLC directory with the following structure: ```json { "@context": ["https://www.w3.org/ns/did/v1"], "id": "did:plc:z72i7hdynmk6r22z27h6tvur", "alsoKnownAs": ["at://bsky.app"], "verificationMethod": [{ "id": "did:plc:z72i7hdynmk6r22z27h6tvur#atproto", "type": "Multikey", "controller": "did:plc:z72i7hdynmk6r22z27h6tvur", "publicKeyMultibase": "zQ3sh..." }], "service": [{ "id": "#atproto_pds", "type": "AtprotoPersonalDataServer", "serviceEndpoint": "https://bsky.social" }] } ``` ## Deployment ### Systemd Service Create `/etc/systemd/system/plcdns.service`: ```ini [Unit] Description=PLC Directory DNS Server After=network.target [Service] Type=simple User=plcdns ExecStart=/usr/local/bin/plcdns -port 53 Restart=always Environment="DNS_PORT=53" [Install] WantedBy=multi-user.target ``` Enable and start: ```bash sudo systemctl enable plcdns sudo systemctl start plcdns ``` ### Docker Compose ```yaml version: '3.8' services: plcdns: build: . ports: - "53:53/udp" - "53:53/tcp" environment: - DNS_PORT=53 restart: unless-stopped ``` ### Running on Port 53 To run on the standard DNS port (53), you need elevated privileges: **Linux (with capabilities):** ```bash sudo setcap 'cap_net_bind_service=+ep' ./plcdns ./plcdns -port 53 ``` **Using sudo:** ```bash sudo ./plcdns -port 53 ``` ## Architecture ``` ┌─────────────┐ │ DNS Client │ └──────┬──────┘ │ Query: _handle..plc.atscan.net ▼ ┌─────────────────┐ │ DNS Server │ │ (Port 8053) │ └────────┬────────┘ │ ├─── Cache Check (5 min TTL) │ ▼ ┌─────────────────┐ │ PLC Directory │ │ (plc.directory) │ └─────────────────┘ │ ▼ DID Document ┌─────────────────┐ │ Parse & Return │ │ TXT Record │ └─────────────────┘ ``` ## Performance - **Cache Hit**: ~1ms response time - **Cache Miss**: ~50-200ms (depends on PLC directory) - **Concurrent Requests**: Supports thousands of concurrent queries - **Memory Usage**: ~10-50MB depending on cache size ## Contributing Contributions are welcome! Please: 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ### Code Style - Follow standard Go conventions - Run `go fmt` before committing - Add tests for new features - Update documentation as needed ## License MIT License - see [LICENSE](LICENSE) file for details ## Related Projects - [AT Protocol](https://atproto.com/) - Authenticated Transfer Protocol - [Bluesky](https://bsky.app/) - Social network built on AT Protocol - [PLC Directory](https://plc.directory/) - DID PLC registry ## Acknowledgments - Built with [miekg/dns](https://github.com/miekg/dns) - DNS library for Go - Inspired by the AT Protocol ecosystem ## Roadmap - [ ] DNSSEC support - [ ] Prometheus metrics endpoint - [ ] Redis cache backend option - [ ] Rate limiting - [ ] Multiple PLC directory fallbacks - [ ] Web UI for testing queries - [ ] REST API endpoint --- **Made with ❤️ for the AT Protocol community**