dns-worker 1.0.2-3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +662 -0
  2. package/README.md +294 -0
  3. package/dist/serverfull.mjs +11777 -0
  4. package/migrations/0000_init.sql +80 -0
  5. package/migrations/0001_move_lists_to_d1.sql +12 -0
  6. package/migrations/0002_activity_tracking.sql +7 -0
  7. package/migrations/0003_fix_profiles_cascade.sql +21 -0
  8. package/migrations/0004_system_settings.sql +12 -0
  9. package/migrations/0005_add_bloom_storage.sql +3 -0
  10. package/migrations/0006_cleanup_profiles_table.sql +18 -0
  11. package/migrations/0007_user_activity_and_totp.sql +37 -0
  12. package/migrations/0008_add_profile_key.sql +8 -0
  13. package/migrations/0009_add_profile_blooms.sql +5 -0
  14. package/migrations/0010_session_device_info.sql +3 -0
  15. package/migrations/0011_session_created_at.sql +2 -0
  16. package/migrations/0012_profile_bloom_chunks.sql +9 -0
  17. package/migrations/0013_add_session_revoked_to_activity_log.sql +29 -0
  18. package/migrations/0014_add_session_geo.sql +3 -0
  19. package/migrations/0015_add_signup_to_activity_log.sql +30 -0
  20. package/migrations/0016_add_session_rotation_counter.sql +2 -0
  21. package/migrations/0017_add_access_points.sql +31 -0
  22. package/migrations/0018_add_list_updated_at.sql +2 -0
  23. package/migrations/0019_add_list_sync_error.sql +2 -0
  24. package/migrations/0020_add_session_last_active.sql +5 -0
  25. package/migrations/0021_add_user_timezone.sql +2 -0
  26. package/migrations/0022_add_user_locale.sql +2 -0
  27. package/migrations/0023_add_user_password_version.sql +2 -0
  28. package/migrations/0024_session_pin_and_pause.sql +37 -0
  29. package/migrations/0025_add_secret_table.sql +10 -0
  30. package/migrations/0026_session_lock_config.sql +2 -0
  31. package/migrations/0027_add_session_id_to_activity_log.sql +2 -0
  32. package/migrations/0028_rename_session_id_to_session_id_hash.sql +2 -0
  33. package/migrations/0029_profile_blooms_staging.sql +12 -0
  34. package/migrations/0030_add_list_blooms.sql +7 -0
  35. package/migrations/0031_list_blooms_chunks.sql +13 -0
  36. package/migrations/0032_profile_blooms_cascade.sql +40 -0
  37. package/migrations/0033_remove_system_secrets.sql +2 -0
  38. package/migrations/0034_remove_list_entries.sql +2 -0
  39. package/migrations/0035_add_envelope_encryption_columns.sql +5 -0
  40. package/migrations/0036_add_cf_proxy_cidrs_setting.sql +7 -0
  41. package/migrations/0037_optimize_logs_composite_indexes.sql +25 -0
  42. package/migrations/0038_optimize_logs_table_and_indexes.sql +49 -0
  43. package/migrations/0039_add_lists_profile_id_index.sql +5 -0
  44. package/migrations/0040_reduce_logs_indexes_write_cost.sql +9 -0
  45. package/migrations/0041_create_log_hourly_rollups.sql +21 -0
  46. package/migrations/0042_add_rule_created_at.sql +3 -0
  47. package/migrations/0043_create_client_hourly_rollups.sql +26 -0
  48. package/migrations/0044_create_destination_hourly_rollups.sql +29 -0
  49. package/migrations/0045_transform_logs_without_rowid.sql +38 -0
  50. package/migrations/0046_add_passkeys.sql +19 -0
  51. package/migrations/0047_add_passkey_actions_to_activity_log.sql +35 -0
  52. package/migrations/0048_add_recovery_key_rotated_to_activity_log.sql +35 -0
  53. package/migrations/0049_optimize_rollups_and_add_domain_rollups.sql +26 -0
  54. package/migrations/0050_add_dest_columns_to_logs.sql +6 -0
  55. package/migrations/0051_add_registration_enabled_setting.sql +2 -0
  56. package/package.json +71 -0
  57. package/static/assets/AccountView-BvRvODjN.js +4 -0
  58. package/static/assets/AnalyticsView-DQ7hDChh.js +2 -0
  59. package/static/assets/AuthView-Bwv6hbdi.js +2 -0
  60. package/static/assets/DestinationMap-BEQNbcb-.js +1 -0
  61. package/static/assets/FilteringView-BWD3e-DS.js +1 -0
  62. package/static/assets/LogsView-kQy7qTGd.js +5 -0
  63. package/static/assets/QRCodeCanvas-X07w5x_G.js +2 -0
  64. package/static/assets/RulesView-3d5hga0L.js +1 -0
  65. package/static/assets/SettingsView-B9D0kPUF.js +1 -0
  66. package/static/assets/SetupView-D7d-Gsdr.js +1 -0
  67. package/static/assets/SwipeableDrawer-B-MfxTWM.js +1 -0
  68. package/static/assets/TrendChart-B20w7SzD.js +53 -0
  69. package/static/assets/allPaths-BEI3QvIM.js +1 -0
  70. package/static/assets/allPathsLoader-DM2JAMeC.js +1 -0
  71. package/static/assets/browser-icErLjuM.js +1 -0
  72. package/static/assets/date-C4b8kvr-.js +1 -0
  73. package/static/assets/de-DE-CXKS_pep.js +10 -0
  74. package/static/assets/es-ES-B2e3ea35.js +10 -0
  75. package/static/assets/formatCountryName-CSBD8pP8.js +1 -0
  76. package/static/assets/fr-FR-1qQHEpoW.js +10 -0
  77. package/static/assets/getFlagEmoji-_Wxhq0lT.js +1 -0
  78. package/static/assets/index-7FKlsF79.js +16 -0
  79. package/static/assets/index-DdQuGqR5.css +2 -0
  80. package/static/assets/ja-JP-CCVeJXwX.js +10 -0
  81. package/static/assets/ko-KR-bQ1okpC2.js +10 -0
  82. package/static/assets/obex_cat_eye_logo-256-CgYNvUIC.webp +0 -0
  83. package/static/assets/paths-CfqdBnl8.js +1 -0
  84. package/static/assets/paths-cc-gUzxh.js +1 -0
  85. package/static/assets/rolldown-runtime-C4Xdq4VV.js +1 -0
  86. package/static/assets/ru-RU-DeRsms_o.js +10 -0
  87. package/static/assets/services-fIMx5oSx.js +1 -0
  88. package/static/assets/splitPathsBySizeLoader-BgBwSA38.js +1 -0
  89. package/static/assets/vendor-i18next-cO7FDf_e.js +1 -0
  90. package/static/assets/vendor-icons-16-BgwRBCeU.js +1 -0
  91. package/static/assets/vendor-icons-20-X5NPN60g.js +1 -0
  92. package/static/assets/vendor-icons-other-Bme3ywH9.js +2 -0
  93. package/static/assets/vendor-react-Kt98jRfM.js +11 -0
  94. package/static/assets/vendor-ui-core-BpucEp_q.js +1 -0
  95. package/static/assets/vendor-utils-CfYGGC23.js +9 -0
  96. package/static/assets/vi-VN-BcXfqmzH.js +10 -0
  97. package/static/assets/zh-CN-D8YK7j27.js +12 -0
  98. package/static/assets/zh-TW-C2_-uaZk.js +12 -0
  99. package/static/favicon.webp +0 -0
  100. package/static/index.html +27 -0
  101. package/static/manifest.webmanifest +1 -0
  102. package/static/registerSW.js +1 -0
  103. package/static/sw.js +1 -0
package/README.md ADDED
@@ -0,0 +1,294 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/Obein/DNS-Worker/main/web/src/assets/obex_cat_eye_logo-256.webp" alt="DNS Worker Logo" width="128">
3
+ <h1>DNS Worker</h1>
4
+ <p>Protective DNS resolver based on Cloudflare Workers & D1</p>
5
+ <p>Protect your first hop on the internet</p>
6
+ <p align="center">
7
+ English | <a href="README_zh-CN.md">中文 (简体)</a> | <a href="README_zh-TW.md">中文 (正體)</a>
8
+ </p>
9
+
10
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
11
+ [![Platform: Cloudflare Workers](https://img.shields.io/badge/Platform-Cloudflare%20Workers-orange.svg)](https://workers.cloudflare.com/)
12
+ </div>
13
+
14
+ ---
15
+
16
+ ## 📖 Introduction
17
+
18
+ **DNS Worker** is a lightweight, scalable, and privacy-focused DNS resolution system. It runs entirely on Cloudflare's edge network, leveraging the ultra-fast response of Workers and the efficient storage of D1 database to provide users with a granular DNS (over HTTPS) control experience.
19
+
20
+ [![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/Obein/DNS-Worker)
21
+
22
+ ### Why DNS Worker?
23
+
24
+ | | Traditional DNS Services | DNS Worker |
25
+ |---|---|---|
26
+ | **Hosting** | Requires a VPS or home server | Runs on Cloudflare's free tier — no server needed |
27
+ | **Latency** | Depends on server location | Edge-computed in 300+ cities worldwide |
28
+ | **Maintenance** | Manual updates, OS patches | Zero-maintenance serverless deployment |
29
+ | **Scaling** | Limited by hardware | Scales automatically with Cloudflare's network |
30
+ | **Cost** | Server fees + electricity | Free for most personal usage |
31
+
32
+ > Deploy your own privacy-respecting DNS resolver in under 5 minutes — no credit card, no server, no DevOps.
33
+
34
+ ### What is DNS over HTTPS (DoH)?
35
+
36
+ DoH (RFC 8484) is a protocol for performing DNS queries via encrypted HTTPS connections. Compared to traditional plaintext DNS, DoH can:
37
+ * **Prevent Hijacking**: Prevents ISPs or third parties from tampering with DNS responses.
38
+ * **Enhance Privacy**: Hides your browsing history through an encrypted tunnel.
39
+ * **Bypass Censorship**: Provides more stable resolution in restricted network environments.
40
+
41
+ ---
42
+
43
+ ## ✨ Core Features
44
+
45
+ - 🚀 **Ultra-fast Resolution**: Fully based on edge computing with extremely low global latency.
46
+ - 🗒️ **Multi-profile Management**: Supports creating multiple independent configurations, each with a unique endpoint.
47
+ - 🛡️ **Granular Filtering**:
48
+ - **Allow/Block Lists**: Supports exact domain and subdomain wildcard matching.
49
+ - **Third-party Rule Sets**: Supports subscribing to external blocklists in formats like AdGuard.
50
+ - **Custom Redirection**: Supports custom overrides for A, AAAA, TXT, and CNAME records.
51
+ - 📊 **Real-time Stats & Logs**: Visual dashboard recording every request's hit reason, geo-location, and upstream latency.
52
+ - 🔐 **Privacy Enhancement**: Flexible ECS (EDNS Client Subnet) configuration (Forward, Custom, or Hidden).
53
+ - 🔒 **Rewrite ECH & ECH Fronting**: Automatically injects/rewrites ECH (Encrypted Client Hello) parameters and customizable Outer SNI (ECH Fronting) for HTTPS (Type 65) / SVCB (Type 64) queries to eliminate plaintext SNI leakage. *(Note: ECH rewriting is exclusively supported for domains proxied by Cloudflare)*.
54
+ - 🌗 **Modern UI**: Dark mode support, high-density management panel built with React + BlueprintJS.
55
+
56
+ ---
57
+
58
+ ## 🖼️ Quick Look
59
+
60
+ | User Login |
61
+ |:---:|
62
+ | ![Login](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-login.webp) |
63
+
64
+ | Setup Guide | Endpoints |
65
+ |:---:|:---:|
66
+ | ![Setup](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-setup.webp) | ![Endpoints](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-endpoints.webp) |
67
+
68
+ | Real-time Analytics | Request Destinations |
69
+ |:---:|:---:|
70
+ | ![Stats](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-stats.webp) | ![Destinations](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-stats_dest.webp) |
71
+
72
+ | Rule Management | External Filters |
73
+ |:---:|:---:|
74
+ | ![Rules](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-rules.webp) | ![Filters](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-filter.webp) |
75
+
76
+ | Resolution Logs | Log Detail |
77
+ |:---:|:---:|
78
+ | ![Resolution Logs](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-log.webp) | ![Log Detail](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-log_detail.webp) |
79
+
80
+ | Profile Settings | Profile Select |
81
+ |:---:|:---:|
82
+ | ![Settings](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-settings.webp) | ![Profile Select](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-profile_select.webp) |
83
+
84
+ | Mobile Logs | Mobile Stats |
85
+ |:---:|:---:|
86
+ | ![Mobile Logs](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-mobile_log.webp) | ![Mobile Stats](https://raw.githubusercontent.com/Obein/DNS-Worker/main/docs/screenshots/dns.obex-mobile_stats.webp) |
87
+
88
+ ---
89
+
90
+ ## 🛠️ Technical Architecture
91
+
92
+ ### Code Structure
93
+ ```text
94
+ ├── src/
95
+ │ ├── index.ts # Entry point, handles HTTP routing & middleware
96
+ │ ├── types.ts # Type definitions
97
+ │ ├── api/ # API Controllers (Auth, Account, Profiles)
98
+ │ ├── lib/ # Core logic (RBAC, Rule filtering)
99
+ │ ├── models/ # D1 Database models
100
+ │ ├── pipeline/ # DNS Resolution Pipeline (Core business logic)
101
+ │ └── utils/ # Utilities (Cache, GeoIP, DNS Codec, Bloom Filter)
102
+ ├── web/ # React/BlueprintJS UI frontend project
103
+ │ ├── public/ # Public static files
104
+ │ ├── src/ # Frontend source code
105
+ │ │ ├── assets/ # Static assets (images, icons, etc.)
106
+ │ │ ├── components/ # Reusable UI components
107
+ │ │ ├── i18n/ # Internationalization (i18n) configuration
108
+ │ │ ├── layouts/ # Layout components (dashboard layout, etc.)
109
+ │ │ ├── routes/ # Frontend routing configuration
110
+ │ │ ├── services/ # Centralized API service wrappers (Auth, Account, Profiles, etc.)
111
+ │ │ ├── views/ # Main pages / views (dashboard, logs, settings, setup, etc.)
112
+ │ │ └── utils/ # Utility helpers and functions
113
+ │ └── package.json # Frontend dependencies configuration
114
+ ├── static/ # Compiled static resources
115
+ ├── migrations/ # D1 Database migration scripts
116
+ └── wrangler.toml # Cloudflare deployment configuration
117
+ ```
118
+
119
+ ### Resolution Pipeline
120
+ When a DNS request arrives, it goes through the following processing stages:
121
+ 1. **Memory Cache Check**: Checks if a valid response for the query exists in the edge node's memory.
122
+ 2. **Config Loading**: Layers profile settings loading from Memory -> Cache API -> D1 Database.
123
+ 3. **Local Rule Matching**:
124
+ - **Whitelist**: If hit, forwards directly to upstream and returns.
125
+ - **Redirection**: If hit, returns custom records.
126
+ - **Blacklist**: If hit, returns NXDOMAIN, 0.0.0.0, or a custom result.
127
+ 4. **External List Filtering**:
128
+ - Use a **Bloom filter** for fast filtering.
129
+ 5. **Upstream Resolution**: If none of the above hit, requests the upstream DoH server based on configuration, with optional ECS support.
130
+ 6. **Async Logging & Caching**: Asynchronously records resolution logs, fetches target GeoIP, and writes results to various cache levels.
131
+
132
+ ---
133
+
134
+ ## 🚀 Deployment Guide
135
+
136
+ ### Online Deployment (Cloudflare Dashboard)
137
+
138
+ 1. **Fork this repo**: Click the `Fork` button at the top right to clone the repository to your own GitHub account.
139
+ 2. **Create D1 Database**: Log in to the Cloudflare dashboard, go to `Workers & Pages` > `D1`, and create a new database (e.g., named `dns_worker_db`), and copy the created database ID.
140
+ 3. **Configure Database ID**: In your forked repository, edit the `wrangler.toml` file and replace `database_id` with the ID of the database you just created.
141
+ 4. **Create Worker**: Go to Cloudflare dashboard `Workers & Pages` > `Create application`.
142
+ 5. **Import from GitHub & Complete Initial Deployment**: On the deployment page, select `Continue with GitHub`, connect your forked project, and complete the authorized deployment. Under the Build & Deploy settings, configure as follows:
143
+ * **Build command**: `npm run build`
144
+ * **Deploy command**: `npm run deploy`
145
+ * **Root directory (Path)**: `/`
146
+ > ⚠️ **Note**: Environment variables entered in the initial project setup wizard are only injected into the build container and will not take effect as runtime secrets. Proceed with the "Deploy" button directly, and configure runtime secrets in your Worker's settings after the initial deployment finishes.
147
+ 6. **Configure JWT Secret**: After the initial deployment completes, go to Cloudflare Dashboard -> `Workers & Pages` -> click on your Worker -> `Settings` -> `Runtime variables and secrets` (or `Variables and secrets`) -> click `Add`. Set the Name to `JWT_SECRET`, choose type `Secret`, input a secure random string as Value, and click `Deploy` (or `Save and Deploy`).
148
+ 7. **Configure KEK for Envelope Encryption (Optional)**: In the same `Settings` > `Runtime variables and secrets` section after deployment, to enable server-side envelope encryption for sensitive credentials (such as TOTP keys and recovery keys) in D1, add a variable named `KEK_v1`, type `Secret`, and input a secure key value. When you need to rotate the KEK key, add a new secret `KEK_v(N+1)` (e.g. `KEK_v2` -> `KEK_v3`, etc.) sequentially.
149
+
150
+ ### Local Development & Manual Deployment
151
+
152
+ #### Development Environment
153
+ - **Node.js**: v18.x or later
154
+ - **Package Manager**: npm
155
+ - **Cloudflare Account**: Workers and D1 permissions required
156
+
157
+ #### Local Setup & Deployment Steps
158
+ 1. Clone the repository and install dependencies:
159
+
160
+ ```bash
161
+ npm install
162
+ ```
163
+
164
+ 2. Initialize D1 Database:
165
+
166
+ ```bash
167
+ npm run db:setup
168
+ npm run db:migrate:dev
169
+ ```
170
+
171
+ 3. Configure environment variables:
172
+ * Create a `.dev.vars` file in the root directory and add a secure random JWT secret (required for session token signing):
173
+ ```env
174
+ JWT_SECRET=your_secure_random_string_here
175
+ ```
176
+ * (Optional) Enable Envelope Encryption for sensitive credentials (like TOTP secrets and recovery keys) by adding a Key Encryption Key (KEK):
177
+ ```env
178
+ KEK_v1=your_secure_kek_v1_key_string
179
+ ```
180
+
181
+ 4. Start the development server:
182
+
183
+ ```bash
184
+ npm run dev
185
+ ```
186
+
187
+ 5. Deploy manually:
188
+
189
+ ```bash
190
+ npm run deploy
191
+ ```
192
+
193
+ ### Serverfull Mode Deployment (Standalone Server / VPS)
194
+
195
+ DNS Worker can run completely independent of Cloudflare Workers as a standalone service on your Linux, Windows, or macOS server. Serverfull mode provides:
196
+ * **Classic UDP DNS (Port 53)**: Standard RFC 1035 UDP DNS resolution service for routers or system DNS settings.
197
+ * **DNS over TLS / DoT (Port 853)**: RFC 7858 encrypted DNS, natively supported by Android 9+ "Private DNS", with SNI-based Profile routing (e.g. `<profile_key>.dns.example.com`).
198
+ * **Web Dashboard & DoH (Default Port 3000)**: Full-featured React management dashboard and REST API.
199
+ * **Local SQLite Database**: Automatically executes schema migrations out-of-the-box without cloud dependencies.
200
+
201
+ #### Environment Variables (Configure in `.env.serverfull`, `.env`, or system environment)
202
+
203
+ | Environment Variable | Description | Default / Example |
204
+ |---|---|---|
205
+ | `SERVERFULL_TLS_KEY_PATH` | Absolute path to TLS private key file (PEM format, alias: `SERFULL_TLS_KEY_PATH`) | `/etc/letsencrypt/live/example.com/privkey.pem` |
206
+ | `SERVERFULL_TLS_CERT_PATH` | Absolute path to TLS certificate chain file (PEM format, alias: `SERVERFULL_TLS_PUB_PATH`) | `/etc/letsencrypt/live/example.com/fullchain.pem` |
207
+ | `SERVERFULL_UDP_PORT` | Classic UDP DNS listening port | `53` |
208
+ | `SERVERFULL_DOT_PORT` | DoT (TLS) listening port | `853` |
209
+ | `SERVERFULL_HTTP_PORT` | HTTP Web Dashboard & DoH listening port | `3000` |
210
+ | `SERVERFULL_HOST` | Listening host IP | `0.0.0.0` |
211
+ | `SERVERFULL_DB_PATH` | Local SQLite database file path | `./data/dns_worker.sqlite` |
212
+ | `SERVERFULL_DEFAULT_PROFILE_KEY` | Default Profile key when no SNI or profile identifier is provided | First created profile |
213
+ | `JWT_SECRET` | Session authentication token secret key | Auto-generated secure random string |
214
+
215
+ #### Quick Start
216
+
217
+ 1. Configure environment variables:
218
+ The project provides an out-of-the-box configuration file `.env.serverfull` (the server automatically loads system environment variables, `.env`, or `.env.serverfull` by priority). You can directly modify `.env.serverfull`, or copy it to `.env` for customization:
219
+ ```bash
220
+ # Edit .env.serverfull directly (or copy via cp .env.serverfull .env first)
221
+ nano .env.serverfull
222
+ ```
223
+
224
+ 2. Build frontend and start Serverfull service:
225
+ ```bash
226
+ npm run start:serverfull
227
+ ```
228
+
229
+ 3. Register as a Linux systemd background service:
230
+ ```bash
231
+ sudo npm run service-create:linux
232
+ sudo systemctl start dns-worker
233
+ sudo systemctl status dns-worker
234
+ ```
235
+ This generates `/etc/systemd/system/dns-worker.service` configured with `CAP_NET_BIND_SERVICE` privileges to bind ports 53 and 853 with automatic restart on boot.
236
+
237
+ ### Online Deployment to Cloudflare Pages (⚠️ Not Recommended)
238
+
239
+ If you wish to deploy the project using Cloudflare Pages (Advanced Mode):
240
+
241
+ > [!WARNING]
242
+ > **Not Recommended**: This project is primarily a DNS resolution service, which is highly sensitive to response latency. Workers, as lightweight edge functions, are much better suited for low-latency DoH resolution tasks compared to Pages Functions. Standard Worker deployment also offers simpler routing and binding management. We strongly suggest deploying via Workers instead.
243
+
244
+ 1. **Create a D1 Database**, copy its ID, and paste it into the `database_id` field in `wrangler.toml`.
245
+ 2. In the Cloudflare Dashboard, go to `Workers & Pages` > `Create application` > `Pages` > `Connect to Git`.
246
+ 3. Select your forked repository, and configure the build settings:
247
+ * **Framework preset**: `None`
248
+ * **Build command**: `npm run build:pages`
249
+ * **Build output directory**: `static`
250
+ 4. After the initial deployment, go to the Pages project's **Settings** > **Functions** > **D1 database bindings**, and add a binding:
251
+ * **Variable name**: `DB`
252
+ * **D1 database**: Select your `dns_worker_db` database.
253
+ 5. Redeploy the Pages project for the bindings to take effect.
254
+
255
+ ---
256
+
257
+ ## 💪 Powered by
258
+
259
+ * [Cloudflare Workers](https://workers.cloudflare.com/)
260
+
261
+ ## 🚚 Dependencies
262
+
263
+ * [Blueprint](https://github.com/palantir/blueprint) (at Palantir)
264
+ * [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss)
265
+ * [React](https://github.com/facebook/react)
266
+
267
+ ---
268
+
269
+ ## 📄 License
270
+
271
+ This project is licensed under the [AGPLv3](LICENSE) License.
272
+
273
+ ---
274
+
275
+ ## 📝 Summary
276
+
277
+ DNS Worker gives you full control over your DNS resolution — with no servers to rent, no infrastructure to manage, and no compromises on privacy. By leveraging Cloudflare Workers' global edge network and D1 database, it delivers a production-ready Protective DNS service that is:
278
+
279
+ - **Free to run** on Cloudflare's generous free tier
280
+ - **Fast everywhere** thanks to 300+ edge locations worldwide
281
+ - **Fully customizable** with per-profile rules, allowlists, blocklists, and third-party filter subscriptions
282
+ - **Privacy-first** with encrypted DoH and flexible ECS controls
283
+ - **Easy to deploy** in minutes via one-click deploy or a simple `npm run deploy`
284
+
285
+ Whether you're protecting a single device or managing DNS for your family, DNS Worker offers an elegant, self-hosted alternative to commercial DNS filtering services — without the cost or complexity.
286
+
287
+ <div align="center">
288
+ <br>
289
+ <a href="https://deploy.workers.cloudflare.com/?url=https://github.com/Obein/DNS-Worker">
290
+ <img src="https://deploy.workers.cloudflare.com/button" alt="Deploy to Cloudflare">
291
+ </a>
292
+ <br><br>
293
+ <b>If DNS Worker is useful to you, please consider giving it a ⭐</b>
294
+ </div>