SupaDNS (Dart / Flutter)
Bypass blocked DNS for Supabase using DNS-over-HTTPS (DoH).
If your ISP blocks *.supabase.co via DNS poisoning, standard Supabase apps will silently fail with SocketException: Failed host lookup. supadns provides a drop-in replacement client that detects these failures and transparently routes the connection through DNS-over-HTTPS (Quad9 and Cloudflare) while preserving strict TLS SNI validation.
Install
Add it to your pubspec.yaml:
dependencies:
supadns: ^1.0.0
supabase: ^2.0.0
Quick Start (with supabase)
SupaDNS provides a createSmartClient that acts exactly like the standard SupabaseClient constructor, but it intercepts requests to handle DoH fallback automatically.
import 'package:supadns/supadns.dart';
void main() async {
// Use this instead of the standard SupabaseClient constructor
final supabase = createSmartClient(
'https://myproject.supabase.co',
'your-anon-key',
);
// All APIs work transparently: Auth, REST, Storage, Functions
final data = await supabase.from('todos').select('*');
print(data);
}
Using with standard HTTP
If you are just making raw HTTP requests, you can use the smartFetch wrapper:
import 'package:supadns/supadns.dart';
import 'dart:convert';
void main() async {
final headers = {
'apikey': 'your-anon-key',
'Authorization': 'Bearer your-anon-key'
};
// Automatically handles DoH fallback if DNS is poisoned/blocked
final resp = await smartFetch(
'https://myproject.supabase.co/rest/v1/todos?select=*',
headers: headers,
);
print('Status: ${resp.statusCode}');
final body = await resp.transform(utf8.decoder).join();
print(body);
}
Standalone DoH Resolution
If you just need to bypass DNS and get the IPv4 address:
import 'package:supadns/supadns.dart';
void main() async {
final ip = await resolveDoH('myproject.supabase.co');
print('Resolved: $ip'); // -> 76.76.21.21
}
How It Works (TLS SNI Preservation)
The hardest part of direct IP connection with Cloudflare is preserving TLS SNI. Dart's standard HttpClient does not allow decoupling DNS resolution from the Host header easily.
- System DNS First: Always tries standard
dart:io HttpClientfirst. If it works, overhead is ~0ms. - Failure Detection: Catches
SocketExceptionandFailed host lookupspecifically for*.supabase.codomains. - DoH Fallback: Resolves the IPv4 address via
https://dns.quad9.net/dns-query(RFC 1035 wire-format). - TLS SNI: Connects a raw TCP socket to the resolved IP, then upgrades it to TLS using
SecureSocket.secure(socket, host: original_host). This ensures Cloudflare's strict edge SSL terminates correctly. TheSecureSocketis then passed intoHttpClient.connectionFactoryto route the HTTP protocols.
Requirements
- Dart ≥ 3.0
License
MIT