在flutter/dart中使用ip进行https请求
为什么要这样做
在已知目标服务器的IP情况下, 直接通过IP访问可以避免DNS污染, 避免出现因错误的DNS解析导致无法访问的情况
要解决的问题
Dart的HttpClient没有给出验证证书的接口, 直接通过IP访问会导致证书验证出错.
我们查询google.com, 得到IP地址59.24.3.174, 然后直接进行访问
import "package:http/http.dart" as http
void main(){
http.get(Uri.parse("https://172.217.163.46"));
}
出现错误
Unhandled exception:
HandshakeException: Handshake error in client (OS Error:
CERTIFICATE_VERIFY_FAILED: IP address mismatch(../../third_party/boringssl/src/ssl/handshake.cc:393))
dart的HttpClient给了一个badCertificateCallback的接口, 但很遗憾, 我们没办法校验证书, 只能这样做
import 'dart:io';
import 'package:http/http.dart' as http;
class CustomOverrides extends HttpOverrides{
@override
HttpClient createHttpClient(SecurityContext? context) {
var client = super.createHttpClient(context);
client.badCertificateCallback = (cert, host, port){
// 没有验证cert的方式
return true;
};
return client;
}
}
void main() async{
HttpOverrides.global = CustomOverrides();
http.get(Uri.parse("https://172.217.163.46"));
}
这样做确实解决了成功访问, 但是安全性存在严重问题
建立代理服务器
要解决这个问题, 我们可以通过代理服务器的方式解决这个问题, 在我们的程序中, 仍然使用域名访问, 在代理服务器中将流量转发至对应的IP
建立代理服务器
直接使用dart:io
即可
import 'dart:convert';
import 'dart:io';
class HttpProxyRequest {
String host;
int port;
final void Function() stop;
HttpProxyRequest(this.host, this.port, this.stop);
}
class _HttpProxyHandler {
var content = "";
late Socket client;
Socket? serverSocket;
void handle(
Socket c, void Function(HttpProxyRequest request) onRequest) async {
try {
client = c;
await for (var d in client) {
if (serverSocket == null) {
content += Utf8Decoder().convert(d);
if (content.contains("\n")) {
if (content.split(" ").first != "CONNECT") {
// 不知道为什么在Windows上有个程序会发来Get请求
client
.write("HTTP/1.1 400 Bad Request\nContent-Type: text/plain\n"
"Content-Length: 29\n\nBad Request: Invalid Request");
client.flush();
client.close();
return;
}
var uri = content
.split('\n')
.first
.split(" ")
.firstWhere((element) => element.contains(":"));
bool stop = false;
var request = HttpProxyRequest(
uri.split(":").first, int.parse(uri.split(":").last), () {
stop = true;
});
onRequest(request);
if (stop) {
client.close();
return;
}
forward(request.host, request.port);
}
}
if (serverSocket != null) {
serverSocket!.add(d);
}
}
close();
} catch (e) {
close();
}
}
void close() {
try {
client.close();
serverSocket?.close();
} catch (e) {
// 忽视已经关闭的情况
}
}
void forward(String host, int port) async {
try {
serverSocket = await Socket.connect(host, port);
serverSocket?.listen((event) {
client.add(event);
}, onDone: () {
client.close();
serverSocket = null;
}, onError: (e) {
client.close();
serverSocket = null;
}, cancelOnError: true);
client.write('HTTP/1.1 200 Connection Established\r\n\r\n');
client.flush();
} catch (e) {
close();
}
}
}
class HttpProxyServer {
void onRequest(HttpProxyRequest request) {
if (request.host == "google.com") {
request.host = "172.217.163.46";
}
}
Future<void> run(int port) async {
var socket = await ServerSocket.bind(InternetAddress.anyIPv4, port);
socket.listen((event) => _HttpProxyHandler().handle(event, onRequest));
}
}
发起请求
import 'dart:io';
import 'package:http/http.dart' as http;
import 'proxy_server.dart';
class CustomOverrides extends HttpOverrides{
@override
HttpClient createHttpClient(SecurityContext? context) {
var client = super.createHttpClient(context);
client.findProxy = (uri) => "PROXY localhost:7891;";
return client;
}
}
void main() async{
HttpProxyServer().run(7891);
HttpOverrides.global = CustomOverrides();
http.get(Uri.parse("https://google.com"));
}
这样就成功访问了