Previously:使用 nginx 代理 NextDNS 的 DoH 服務
使用 Cloudflare Worker 代理 NextDNS 的 DoH 服務
使用 tina-hello 的 doh-cf-workers 項目可以方便的建立一個 DoH 代理。由於只需要一個 index.js 文件,所以我這裡轉載一下。默認的示例是 Cloudflare 的 DoH,切換成 NextDNS 的話只需要修改 doh 和 dohjson 的網址,其他都不用動。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | // SPDX-License-Identifier: 0BSD const doh = 'https://dns.nextdns.io/YOUR_ID/YOUR_TAG' const dohjson = 'https://dns.nextdns.io/YOUR_ID/YOUR_TAG' const contype = 'application/dns-message' const jstontype = 'application/dns-json' const r404 = new Response( null , {status: 404}); // developers.cloudflare.com/workers/runtime-apis/fetch-event/#syntax-module-worker export default { async fetch(r, env, ctx) { return handleRequest(r); }, }; async function handleRequest(request) { // when res is a Promise<Response>, it reduces billed wall-time // blog.cloudflare.com/workers-optimization-reduces-your-bill let res = r404; const { method, headers, url } = request const searchParams = new URL(url).searchParams if (method == 'GET' && searchParams.has( 'dns' )) { res = fetch(doh + '?dns=' + searchParams.get( 'dns' ), { method: 'GET' , headers: { 'Accept' : contype, } }); } else if (method === 'POST' && headers.get( 'content-type' ) === contype) { // streaming out the request body is optimal than awaiting on it const rostream = request.body; res = fetch(doh, { method: 'POST' , headers: { 'Accept' : contype, 'Content-Type' : contype, }, body: rostream, }); } else if (method === 'GET' && headers.get( 'Accept' ) === jstontype) { const search = new URL(url).search res = fetch(dohjson + search, { method: 'GET' , headers: { 'Accept' : jstontype, } }); } return res; } |
1 2 3 | #測試下 GET 請求 curl -H 'accept: application/dns-json' 'https://YOURPROJECT.YOURWORKER.workers.dev/dns-query?name=ft.shaman.eu.org&type=A' #POST請求由於需要構造 DNS 參數,所以就不測了 |
使用 Python 代理 NextDNS 的 DoH 服務
輕量級的 API 框架我不熟悉,所以這裡還是用 Django。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #file:app1/views.py from django.http import HttpResponse from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt import requests @csrf_exempt def forward_to_doh(request): contype = 'application/dns-message' jstontype = 'application/dns-json' try : if request.method = = 'GET' : if 'dns' in request.GET: params = { 'dns' : request.GET[ 'dns' ]} headers = { 'Accept' : contype} response = requests.get(cloudflare_doh_url, params = params, headers = headers) return JsonResponse(response.json(), status = response.status_code) elif request.headers.get( 'Accept' ) = = jstontype: response = requests.get(cloudflare_doh_url + '?' + request.GET.urlencode(), headers = { 'Accept' : jstontype}) return JsonResponse(response.json(), status = response.status_code) elif request.method = = 'POST' : if request.headers.get( 'content-type' ) = = contype: headers = { 'Accept' : contype, 'Content-Type' : contype} data = request.body response = requests.post(cloudflare_doh_url, data = data, headers = headers) return HttpResponse(response.content, content_type = response.headers[ 'Content-Type' ], status = response.status_code) else : return JsonResponse({ 'error' : 'Unsupported request method' }, status = 405 ) return JsonResponse({ 'error' : 'Not Found' }, status = 404 ) except requests.exceptions.RequestException as e: return JsonResponse({ 'error' : str (e)}, status = 500 ) |
1 2 3 4 5 6 7 8 | #file:mysite/urls.py from django.urls import include,path from app1 import views urlpatterns = [ path( 'YourSecNextDns/' , views.forward_to_doh, name = 'forward_to_doh' ), path( 'i/' , include( 'i.urls' )), ] |
1 2 | #測試下 GET 請求 curl -H 'accept: application/dns-json' 'https://YOUR_DOMAIN.LTD/YourSecNextDns/?name=ft.shaman.eu.org&type=A' |
上面的請求經過三次請求,速度(高達秒級)自然是比不了直連。但是為了體驗 DoH,還是可以用用看。反正網速本身也不快,DNS 慢一點完全可以怪到網速上。