Previously:使用 nginx 代理 NextDNS 的 DoH 服務
使用 Cloudflare Worker 代理 NextDNS 的 DoH 服務
使用 tina-hello 的 doh-cf-workers 項目可以方便的建立一個 DoH 代理。由於只需要一個 index.js 文件,所以我這裡轉載一下。默認的示例是 Cloudflare 的 DoH,切換成 NextDNS 的話只需要修改 doh 和 dohjson 的網址,其他都不用動。
// 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; }
#測試下 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。
#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): cloudflare_doh_url = "https://YOURPROJECT.YOURWORKER.workers.dev/" 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)
#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')), ]
#測試下 GET 請求 curl -H 'accept: application/dns-json' 'https://YOUR_DOMAIN.LTD/YourSecNextDns/?name=ft.shaman.eu.org&type=A'
上面的請求經過三次請求,速度(高達秒級)自然是比不了直連。但是為了體驗 DoH,還是可以用用看。反正網速本身也不快,DNS 慢一點完全可以怪到網速上。