IPv6检测工具
检测结果
检测项目 | 状态 | 详情 | IPv6地址 |
---|---|---|---|
|
检测中...
正在检测IPv6支持情况...
IPv6知识介绍
IPv6简介
IPv6(Internet Protocol version 6)是互联网协议的最新版本,用于替代IPv4。 它提供了更大的地址空间、更好的安全性、自动配置等优势。
- 地址空间: 128位地址,理论上可提供2^128个地址
- 自动配置: 支持无状态地址自动配置
- 安全性: 内置IPsec支持
- 性能: 简化的头部结构,提高路由效率
IPv6检测项目
- AAAA记录: 检查域名是否有IPv6地址记录
- IPv6连通性: 测试IPv6地址是否可达
- DNS解析: 验证IPv6 DNS解析是否正常
- 网络延迟: 测量IPv6连接的网络延迟
- 双栈支持: 检查是否同时支持IPv4和IPv6
示例代码
各语言示例代码
-
IPv6CheckTool (JAVA)
1import java.io.IOException; 2import java.net.InetAddress; 3import java.net.InetSocketAddress; 4import java.net.Socket; 5import java.net.UnknownHostException; 6import java.time.LocalDateTime; 7import java.time.format.DateTimeFormatter; 8import java.util.*; 9import java.util.concurrent.*; 10 11/** 12 * IPv6检测工具 - Java实现 13 * 检测网站是否支持IPv6访问 14 */ 15public class IPv6CheckTool { 16 17 private final List<String> defaultNameservers; 18 private final int timeout; 19 20 public IPv6CheckTool() { 21 this.defaultNameservers = Arrays.asList( 22 "2001:4860:4860::8888", // Google DNS IPv6 23 "2001:4860:4860::8844", // Google DNS IPv6备用 24 "2606:4700:4700::1111", // Cloudflare DNS IPv6 25 "2606:4700:4700::1001" // Cloudflare DNS IPv6备用 26 ); 27 this.timeout = 10000; // 10秒 28 } 29 30 /** 31 * 测试结果类 32 */ 33 public static class TestResult { 34 private String test; 35 private String status; 36 private String statusText; 37 private String details; 38 private List<String> ipv6Addresses; 39 private Map<String, Object> additionalData; 40 41 public TestResult(String test, String status, String statusText, String details) { 42 this.test = test; 43 this.status = status; 44 this.statusText = statusText; 45 this.details = details; 46 this.ipv6Addresses = new ArrayList<>(); 47 this.additionalData = new HashMap<>(); 48 } 49 50 // Getters and Setters 51 public String getTest() { return test; } 52 public void setTest(String test) { this.test = test; } 53 54 public String getStatus() { return status; } 55 public void setStatus(String status) { this.status = status; } 56 57 public String getStatusText() { return statusText; } 58 public void setStatusText(String statusText) { this.statusText = statusText; } 59 60 public String getDetails() { return details; } 61 public void setDetails(String details) { this.details = details; } 62 63 public List<String> getIpv6Addresses() { return ipv6Addresses; } 64 public void setIpv6Addresses(List<String> ipv6Addresses) { this.ipv6Addresses = ipv6Addresses; } 65 66 public Map<String, Object> getAdditionalData() { return additionalData; } 67 public void setAdditionalData(Map<String, Object> additionalData) { this.additionalData = additionalData; } 68 } 69 70 /** 71 * 检测结果类 72 */ 73 public static class CheckResult { 74 private String domain; 75 private String timestamp; 76 private List<TestResult> tests; 77 private Map<String, Object> summary; 78 79 public CheckResult(String domain) { 80 this.domain = domain; 81 this.timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); 82 this.tests = new ArrayList<>(); 83 this.summary = new HashMap<>(); 84 } 85 86 // Getters and Setters 87 public String getDomain() { return domain; } 88 public void setDomain(String domain) { this.domain = domain; } 89 90 public String getTimestamp() { return timestamp; } 91 public void setTimestamp(String timestamp) { this.timestamp = timestamp; } 92 93 public List<TestResult> getTests() { return tests; } 94 public void setTests(List<TestResult> tests) { this.tests = tests; } 95 96 public Map<String, Object> getSummary() { return summary; } 97 public void setSummary(Map<String, Object> summary) { this.summary = summary; } 98 } 99 100 /** 101 * 检测选项类 102 */ 103 public static class CheckOptions { 104 private boolean checkAAAA = true; 105 private boolean checkConnectivity = true; 106 private boolean checkDNS = true; 107 private boolean checkLatency = true; 108 109 public CheckOptions() {} 110 111 public CheckOptions(boolean checkAAAA, boolean checkConnectivity, boolean checkDNS, boolean checkLatency) { 112 this.checkAAAA = checkAAAA; 113 this.checkConnectivity = checkConnectivity; 114 this.checkDNS = checkDNS; 115 this.checkLatency = checkLatency; 116 } 117 118 // Getters and Setters 119 public boolean isCheckAAAA() { return checkAAAA; } 120 public void setCheckAAAA(boolean checkAAAA) { this.checkAAAA = checkAAAA; } 121 122 public boolean isCheckConnectivity() { return checkConnectivity; } 123 public void setCheckConnectivity(boolean checkConnectivity) { this.checkConnectivity = checkConnectivity; } 124 125 public boolean isCheckDNS() { return checkDNS; } 126 public void setCheckDNS(boolean checkDNS) { this.checkDNS = checkDNS; } 127 128 public boolean isCheckLatency() { return checkLatency; } 129 public void setCheckLatency(boolean checkLatency) { this.checkLatency = checkLatency; } 130 } 131 132 /** 133 * 检测域名的IPv6支持情况 134 */ 135 public CheckResult checkIPv6Support(String domain, CheckOptions options) { 136 CheckResult result = new CheckResult(domain); 137 138 try { 139 // 检测AAAA记录 140 if (options.isCheckAAAA()) { 141 TestResult aaaaResult = checkAAAARecord(domain); 142 result.getTests().add(aaaaResult); 143 } 144 145 // 检测IPv6连通性 146 if (options.isCheckConnectivity()) { 147 TestResult connectivityResult = checkIPv6Connectivity(domain); 148 result.getTests().add(connectivityResult); 149 } 150 151 // 检测DNS解析 152 if (options.isCheckDNS()) { 153 TestResult dnsResult = checkDNSResolution(domain); 154 result.getTests().add(dnsResult); 155 } 156 157 // 检测网络延迟 158 if (options.isCheckLatency()) { 159 TestResult latencyResult = checkLatency(domain); 160 result.getTests().add(latencyResult); 161 } 162 163 // 生成总结 164 result.setSummary(generateSummary(result.getTests())); 165 166 } catch (Exception e) { 167 System.err.println("IPv6检测失败: " + e.getMessage()); 168 throw new RuntimeException(e); 169 } 170 171 return result; 172 } 173 174 /** 175 * 检测AAAA记录 176 */ 177 private TestResult checkAAAARecord(String domain) { 178 List<String> ipv6Addresses = new ArrayList<>(); 179 180 try { 181 // 使用InetAddress查询IPv6地址 182 InetAddress[] addresses = InetAddress.getAllByName(domain); 183 for (InetAddress address : addresses) { 184 if (address.getHostAddress().contains(":")) { // IPv6地址包含冒号 185 ipv6Addresses.add(address.getHostAddress()); 186 } 187 } 188 189 if (!ipv6Addresses.isEmpty()) { 190 TestResult result = new TestResult( 191 "AAAA记录检测", 192 "success", 193 "支持", 194 "找到 " + ipv6Addresses.size() + " 个IPv6地址记录" 195 ); 196 result.setIpv6Addresses(ipv6Addresses); 197 return result; 198 } else { 199 TestResult result = new TestResult( 200 "AAAA记录检测", 201 "error", 202 "不支持", 203 "域名未配置IPv6地址记录" 204 ); 205 result.setIpv6Addresses(new ArrayList<>()); 206 return result; 207 } 208 209 } catch (UnknownHostException e) { 210 TestResult result = new TestResult( 211 "AAAA记录检测", 212 "error", 213 "检测失败", 214 "DNS查询失败: " + e.getMessage() 215 ); 216 result.setIpv6Addresses(new ArrayList<>()); 217 return result; 218 } 219 } 220 221 /** 222 * 检测IPv6连通性 223 */ 224 private TestResult checkIPv6Connectivity(String domain) { 225 // 首先获取IPv6地址 226 TestResult aaaaResult = checkAAAARecord(domain); 227 228 if ("error".equals(aaaaResult.getStatus())) { 229 TestResult result = new TestResult( 230 "IPv6连通性检测", 231 "error", 232 "无法检测", 233 "无法获取IPv6地址进行连通性检测" 234 ); 235 result.setIpv6Addresses(new ArrayList<>()); 236 return result; 237 } 238 239 // 测试IPv6地址连通性 240 List<Map<String, Object>> connectivityResults = new ArrayList<>(); 241 int reachableCount = 0; 242 243 for (String ipv6Address : aaaaResult.getIpv6Addresses()) { 244 long startTime = System.currentTimeMillis(); 245 boolean reachable = false; 246 long latency = 0; 247 248 try (Socket socket = new Socket()) { 249 socket.connect(new InetSocketAddress(ipv6Address, 80), 5000); 250 reachable = true; 251 latency = System.currentTimeMillis() - startTime; 252 reachableCount++; 253 } catch (IOException e) { 254 // 连接失败 255 } 256 257 Map<String, Object> result = new HashMap<>(); 258 result.put("ipv6_address", ipv6Address); 259 result.put("reachable", reachable); 260 result.put("latency", latency); 261 connectivityResults.add(result); 262 } 263 264 int totalCount = connectivityResults.size(); 265 266 if (reachableCount == totalCount) { 267 TestResult result = new TestResult( 268 "IPv6连通性检测", 269 "success", 270 "完全可达", 271 "所有 " + totalCount + " 个IPv6地址都可以访问" 272 ); 273 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 274 result.getAdditionalData().put("connectivity_results", connectivityResults); 275 return result; 276 } else if (reachableCount > 0) { 277 TestResult result = new TestResult( 278 "IPv6连通性检测", 279 "warning", 280 "部分可达", 281 reachableCount + "/" + totalCount + " 个IPv6地址可以访问" 282 ); 283 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 284 result.getAdditionalData().put("connectivity_results", connectivityResults); 285 return result; 286 } else { 287 TestResult result = new TestResult( 288 "IPv6连通性检测", 289 "error", 290 "不可达", 291 "所有IPv6地址都无法访问" 292 ); 293 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 294 result.getAdditionalData().put("connectivity_results", connectivityResults); 295 return result; 296 } 297 } 298 299 /** 300 * 检测DNS解析 301 */ 302 private TestResult checkDNSResolution(String domain) { 303 List<String> ipv6Addresses = new ArrayList<>(); 304 305 try { 306 // 使用InetAddress查询IPv6地址 307 InetAddress[] addresses = InetAddress.getAllByName(domain); 308 for (InetAddress address : addresses) { 309 if (address.getHostAddress().contains(":")) { // IPv6地址包含冒号 310 ipv6Addresses.add(address.getHostAddress()); 311 } 312 } 313 314 if (!ipv6Addresses.isEmpty()) { 315 TestResult result = new TestResult( 316 "DNS解析检测", 317 "success", 318 "正常", 319 "IPv6 DNS解析正常" 320 ); 321 result.setIpv6Addresses(ipv6Addresses); 322 return result; 323 } else { 324 TestResult result = new TestResult( 325 "DNS解析检测", 326 "warning", 327 "部分正常", 328 "IPv6 DNS解析部分正常" 329 ); 330 result.setIpv6Addresses(new ArrayList<>()); 331 return result; 332 } 333 334 } catch (UnknownHostException e) { 335 TestResult result = new TestResult( 336 "DNS解析检测", 337 "error", 338 "异常", 339 "DNS解析异常: " + e.getMessage() 340 ); 341 result.setIpv6Addresses(new ArrayList<>()); 342 return result; 343 } 344 } 345 346 /** 347 * 检测网络延迟 348 */ 349 private TestResult checkLatency(String domain) { 350 // 获取IPv6地址 351 TestResult aaaaResult = checkAAAARecord(domain); 352 353 if ("error".equals(aaaaResult.getStatus())) { 354 TestResult result = new TestResult( 355 "网络延迟检测", 356 "error", 357 "无法检测", 358 "无法获取IPv6地址进行延迟检测" 359 ); 360 result.setIpv6Addresses(new ArrayList<>()); 361 return result; 362 } 363 364 // 测试延迟 365 List<Map<String, Object>> latencyResults = new ArrayList<>(); 366 double totalLatency = 0; 367 int validCount = 0; 368 369 for (String ipv6Address : aaaaResult.getIpv6Addresses()) { 370 long startTime = System.currentTimeMillis(); 371 double latency = 0; 372 String status; 373 374 try (Socket socket = new Socket()) { 375 socket.connect(new InetSocketAddress(ipv6Address, 80), 5000); 376 latency = System.currentTimeMillis() - startTime; 377 totalLatency += latency; 378 validCount++; 379 380 if (latency < 100) { 381 status = "excellent"; 382 } else if (latency < 200) { 383 status = "good"; 384 } else { 385 status = "poor"; 386 } 387 } catch (IOException e) { 388 latency = 0; 389 status = "failed"; 390 } 391 392 Map<String, Object> result = new HashMap<>(); 393 result.put("ipv6_address", ipv6Address); 394 result.put("latency", latency); 395 result.put("status", status); 396 latencyResults.add(result); 397 } 398 399 double avgLatency = 0; 400 String resultStatus, statusText, details; 401 402 if (validCount > 0) { 403 avgLatency = totalLatency / validCount; 404 if (avgLatency < 100) { 405 resultStatus = "success"; 406 statusText = "优秀"; 407 } else if (avgLatency < 200) { 408 resultStatus = "warning"; 409 statusText = "良好"; 410 } else { 411 resultStatus = "error"; 412 statusText = "较差"; 413 } 414 details = String.format("平均延迟: %.1fms", avgLatency); 415 } else { 416 resultStatus = "error"; 417 statusText = "检测失败"; 418 details = "无法获取有效延迟数据"; 419 avgLatency = 0; 420 } 421 422 TestResult result = new TestResult( 423 "网络延迟检测", 424 resultStatus, 425 statusText, 426 details 427 ); 428 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 429 result.getAdditionalData().put("latency_results", latencyResults); 430 result.getAdditionalData().put("average_latency", avgLatency); 431 432 return result; 433 } 434 435 /** 436 * 生成检测总结 437 */ 438 private Map<String, Object> generateSummary(List<TestResult> tests) { 439 int successCount = 0; 440 int warningCount = 0; 441 int errorCount = 0; 442 443 for (TestResult test : tests) { 444 switch (test.getStatus()) { 445 case "success": 446 successCount++; 447 break; 448 case "warning": 449 warningCount++; 450 break; 451 case "error": 452 errorCount++; 453 break; 454 } 455 } 456 457 int totalCount = tests.size(); 458 String status, title, message; 459 460 if (successCount == totalCount) { 461 status = "success"; 462 title = "IPv6支持良好"; 463 message = "所有 " + totalCount + " 个检测项目都通过,该网站完全支持IPv6访问。"; 464 } else if (successCount > 0 || warningCount > 0) { 465 status = "warning"; 466 title = "IPv6部分支持"; 467 message = successCount + " 个项目通过," + warningCount + " 个项目警告," + errorCount + " 个项目失败。该网站对IPv6的支持有限。"; 468 } else { 469 status = "error"; 470 title = "IPv6不支持"; 471 message = "所有 " + totalCount + " 个检测项目都失败,该网站不支持IPv6访问。"; 472 } 473 474 Map<String, Object> summary = new HashMap<>(); 475 summary.put("status", status); 476 summary.put("title", title); 477 summary.put("message", message); 478 479 Map<String, Integer> statistics = new HashMap<>(); 480 statistics.put("total", totalCount); 481 statistics.put("success", successCount); 482 statistics.put("warning", warningCount); 483 statistics.put("error", errorCount); 484 summary.put("statistics", statistics); 485 486 return summary; 487 } 488 489 /** 490 * 批量检测多个域名 491 */ 492 public Map<String, Object> batchCheck(List<String> domains, CheckOptions options) { 493 Map<String, Object> results = new HashMap<>(); 494 ExecutorService executor = Executors.newFixedThreadPool(5); 495 496 try { 497 List<Future<Map.Entry<String, Object>>> futures = new ArrayList<>(); 498 499 for (String domain : domains) { 500 Future<Map.Entry<String, Object>> future = executor.submit(() -> { 501 try { 502 CheckResult result = checkIPv6Support(domain, options); 503 return new AbstractMap.SimpleEntry<>(domain, result); 504 } catch (Exception e) { 505 Map<String, Object> errorResult = new HashMap<>(); 506 errorResult.put("error", e.getMessage()); 507 errorResult.put("domain", domain); 508 errorResult.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); 509 return new AbstractMap.SimpleEntry<>(domain, errorResult); 510 } 511 }); 512 futures.add(future); 513 } 514 515 for (Future<Map.Entry<String, Object>> future : futures) { 516 try { 517 Map.Entry<String, Object> entry = future.get(); 518 results.put(entry.getKey(), entry.getValue()); 519 } catch (Exception e) { 520 System.err.println("批量检测失败: " + e.getMessage()); 521 } 522 } 523 524 } finally { 525 executor.shutdown(); 526 } 527 528 return results; 529 } 530 531 /** 532 * 验证IPv6地址格式 533 */ 534 public boolean isValidIPv6(String ipv6) { 535 try { 536 InetAddress.getByName(ipv6); 537 return ipv6.contains(":"); 538 } catch (UnknownHostException e) { 539 return false; 540 } 541 } 542 543 /** 544 * 使用示例 545 */ 546 public static void main(String[] args) { 547 IPv6CheckTool ipv6Tool = new IPv6CheckTool(); 548 549 try { 550 // 单个域名检测 551 System.out.println("检测单个域名:"); 552 CheckResult result = ipv6Tool.checkIPv6Support("google.com", new CheckOptions(true, true, true, true)); 553 System.out.println("域名: " + result.getDomain()); 554 System.out.println("时间: " + result.getTimestamp()); 555 System.out.println("测试数量: " + result.getTests().size()); 556 System.out.println("总结: " + result.getSummary()); 557 558 // 批量检测 559 System.out.println("\n批量检测:"); 560 List<String> domains = Arrays.asList("google.com", "github.com", "facebook.com"); 561 Map<String, Object> batchResults = ipv6Tool.batchCheck(domains, new CheckOptions(true, false, true, false)); 562 System.out.println("批量检测结果: " + batchResults.size() + " 个域名"); 563 564 } catch (Exception e) { 565 System.err.println("检测失败: " + e.getMessage()); 566 } 567 } 568}
-
ipv6_check (GO)
1package main 2 3import ( 4 "encoding/json" 5 "fmt" 6 "net" 7 "sync" 8 "time" 9) 10 11// TestResult 测试结果结构体 12type TestResult struct { 13 Test string `json:"test"` 14 Status string `json:"status"` 15 StatusText string `json:"status_text"` 16 Details string `json:"details"` 17 IPv6Addresses []string `json:"ipv6_addresses"` 18 AdditionalData map[string]interface{} `json:"additional_data,omitempty"` 19} 20 21// CheckResult 检测结果结构体 22type CheckResult struct { 23 Domain string `json:"domain"` 24 Timestamp string `json:"timestamp"` 25 Tests []TestResult `json:"tests"` 26 Summary map[string]interface{} `json:"summary"` 27} 28 29// Summary 总结信息结构体 30type Summary struct { 31 Status string `json:"status"` 32 Title string `json:"title"` 33 Message string `json:"message"` 34 Statistics map[string]int `json:"statistics"` 35} 36 37// IPv6CheckTool IPv6检测工具 38type IPv6CheckTool struct { 39 defaultNameservers []string 40 timeout time.Duration 41} 42 43// NewIPv6CheckTool 创建新的IPv6检测工具实例 44func NewIPv6CheckTool() *IPv6CheckTool { 45 return &IPv6CheckTool{ 46 defaultNameservers: []string{ 47 "2001:4860:4860::8888", // Google DNS IPv6 48 "2001:4860:4860::8844", // Google DNS IPv6备用 49 "2606:4700:4700::1111", // Cloudflare DNS IPv6 50 "2606:4700:4700::1001", // Cloudflare DNS IPv6备用 51 }, 52 timeout: 10 * time.Second, 53 } 54} 55 56// CheckOptions 检测选项 57type CheckOptions struct { 58 CheckAAAA bool `json:"check_aaaa"` 59 CheckConnectivity bool `json:"check_connectivity"` 60 CheckDNS bool `json:"check_dns"` 61 CheckLatency bool `json:"check_latency"` 62} 63 64// CheckIPv6Support 检测域名的IPv6支持情况 65func (t *IPv6CheckTool) CheckIPv6Support(domain string, options CheckOptions) (*CheckResult, error) { 66 result := &CheckResult{ 67 Domain: domain, 68 Timestamp: time.Now().Format("2006-01-02 15:04:05"), 69 Tests: []TestResult{}, 70 } 71 72 // 检测AAAA记录 73 if options.CheckAAAA { 74 aaaaResult := t.checkAAAARecord(domain) 75 result.Tests = append(result.Tests, aaaaResult) 76 } 77 78 // 检测IPv6连通性 79 if options.CheckConnectivity { 80 connectivityResult := t.checkIPv6Connectivity(domain) 81 result.Tests = append(result.Tests, connectivityResult) 82 } 83 84 // 检测DNS解析 85 if options.CheckDNS { 86 dnsResult := t.checkDNSResolution(domain) 87 result.Tests = append(result.Tests, dnsResult) 88 } 89 90 // 检测网络延迟 91 if options.CheckLatency { 92 latencyResult := t.checkLatency(domain) 93 result.Tests = append(result.Tests, latencyResult) 94 } 95 96 // 生成总结 97 result.Summary = t.generateSummary(result.Tests) 98 99 return result, nil 100} 101 102// checkAAAARecord 检测AAAA记录 103func (t *IPv6CheckTool) checkAAAARecord(domain string) TestResult { 104 ipv6Addresses := []string{} 105 106 // 使用net.LookupIP查询IPv6地址 107 ips, err := net.LookupIP(domain) 108 if err == nil { 109 for _, ip := range ips { 110 if ip.To4() == nil && ip.To16() != nil { 111 ipv6Addresses = append(ipv6Addresses, ip.String()) 112 } 113 } 114 } 115 116 if len(ipv6Addresses) > 0 { 117 return TestResult{ 118 Test: "AAAA记录检测", 119 Status: "success", 120 StatusText: "支持", 121 Details: fmt.Sprintf("找到 %d 个IPv6地址记录", len(ipv6Addresses)), 122 IPv6Addresses: ipv6Addresses, 123 } 124 } else { 125 return TestResult{ 126 Test: "AAAA记录检测", 127 Status: "error", 128 StatusText: "不支持", 129 Details: "域名未配置IPv6地址记录", 130 IPv6Addresses: []string{}, 131 } 132 } 133} 134 135// checkIPv6Connectivity 检测IPv6连通性 136func (t *IPv6CheckTool) checkIPv6Connectivity(domain string) TestResult { 137 // 首先获取IPv6地址 138 aaaaResult := t.checkAAAARecord(domain) 139 140 if aaaaResult.Status == "error" { 141 return TestResult{ 142 Test: "IPv6连通性检测", 143 Status: "error", 144 StatusText: "无法检测", 145 Details: "无法获取IPv6地址进行连通性检测", 146 IPv6Addresses: []string{}, 147 } 148 } 149 150 // 测试IPv6地址连通性 151 connectivityResults := []map[string]interface{}{} 152 reachableCount := 0 153 154 for _, ipv6Address := range aaaaResult.IPv6Addresses { 155 startTime := time.Now() 156 reachable := false 157 var latency float64 158 159 // 尝试连接IPv6地址 160 conn, err := net.DialTimeout("tcp6", net.JoinHostPort(ipv6Address, "80"), 5*time.Second) 161 if err == nil { 162 conn.Close() 163 reachable = true 164 latency = float64(time.Since(startTime).Milliseconds()) 165 reachableCount++ 166 } 167 168 connectivityResults = append(connectivityResults, map[string]interface{}{ 169 "ipv6_address": ipv6Address, 170 "reachable": reachable, 171 "latency": latency, 172 }) 173 } 174 175 totalCount := len(connectivityResults) 176 177 if reachableCount == totalCount { 178 return TestResult{ 179 Test: "IPv6连通性检测", 180 Status: "success", 181 StatusText: "完全可达", 182 Details: fmt.Sprintf("所有 %d 个IPv6地址都可以访问", totalCount), 183 IPv6Addresses: aaaaResult.IPv6Addresses, 184 AdditionalData: map[string]interface{}{ 185 "connectivity_results": connectivityResults, 186 }, 187 } 188 } else if reachableCount > 0 { 189 return TestResult{ 190 Test: "IPv6连通性检测", 191 Status: "warning", 192 StatusText: "部分可达", 193 Details: fmt.Sprintf("%d/%d 个IPv6地址可以访问", reachableCount, totalCount), 194 IPv6Addresses: aaaaResult.IPv6Addresses, 195 AdditionalData: map[string]interface{}{ 196 "connectivity_results": connectivityResults, 197 }, 198 } 199 } else { 200 return TestResult{ 201 Test: "IPv6连通性检测", 202 Status: "error", 203 StatusText: "不可达", 204 Details: "所有IPv6地址都无法访问", 205 IPv6Addresses: aaaaResult.IPv6Addresses, 206 AdditionalData: map[string]interface{}{ 207 "connectivity_results": connectivityResults, 208 }, 209 } 210 } 211} 212 213// checkDNSResolution 检测DNS解析 214func (t *IPv6CheckTool) checkDNSResolution(domain string) TestResult { 215 ipv6Addresses := []string{} 216 217 // 使用net.LookupIP查询IPv6地址 218 ips, err := net.LookupIP(domain) 219 if err == nil { 220 for _, ip := range ips { 221 if ip.To4() == nil && ip.To16() != nil { 222 ipv6Addresses = append(ipv6Addresses, ip.String()) 223 } 224 } 225 } 226 227 if len(ipv6Addresses) > 0 { 228 return TestResult{ 229 Test: "DNS解析检测", 230 Status: "success", 231 StatusText: "正常", 232 Details: "IPv6 DNS解析正常", 233 IPv6Addresses: ipv6Addresses, 234 } 235 } else { 236 return TestResult{ 237 Test: "DNS解析检测", 238 Status: "warning", 239 StatusText: "部分正常", 240 Details: "IPv6 DNS解析部分正常", 241 IPv6Addresses: []string{}, 242 } 243 } 244} 245 246// checkLatency 检测网络延迟 247func (t *IPv6CheckTool) checkLatency(domain string) TestResult { 248 // 获取IPv6地址 249 aaaaResult := t.checkAAAARecord(domain) 250 251 if aaaaResult.Status == "error" { 252 return TestResult{ 253 Test: "网络延迟检测", 254 Status: "error", 255 StatusText: "无法检测", 256 Details: "无法获取IPv6地址进行延迟检测", 257 IPv6Addresses: []string{}, 258 } 259 } 260 261 // 测试延迟 262 latencyResults := []map[string]interface{}{} 263 var totalLatency float64 264 validCount := 0 265 266 for _, ipv6Address := range aaaaResult.IPv6Addresses { 267 startTime := time.Now() 268 var latency float64 269 var status string 270 271 // 尝试连接IPv6地址 272 conn, err := net.DialTimeout("tcp6", net.JoinHostPort(ipv6Address, "80"), 5*time.Second) 273 if err == nil { 274 conn.Close() 275 latency = float64(time.Since(startTime).Milliseconds()) 276 totalLatency += latency 277 validCount++ 278 279 if latency < 100 { 280 status = "excellent" 281 } else if latency < 200 { 282 status = "good" 283 } else { 284 status = "poor" 285 } 286 } else { 287 latency = 0 288 status = "failed" 289 } 290 291 latencyResults = append(latencyResults, map[string]interface{}{ 292 "ipv6_address": ipv6Address, 293 "latency": latency, 294 "status": status, 295 }) 296 } 297 298 var avgLatency float64 299 var resultStatus, statusText, details string 300 301 if validCount > 0 { 302 avgLatency = totalLatency / float64(validCount) 303 if avgLatency < 100 { 304 resultStatus = "success" 305 statusText = "优秀" 306 } else if avgLatency < 200 { 307 resultStatus = "warning" 308 statusText = "良好" 309 } else { 310 resultStatus = "error" 311 statusText = "较差" 312 } 313 details = fmt.Sprintf("平均延迟: %.1fms", avgLatency) 314 } else { 315 resultStatus = "error" 316 statusText = "检测失败" 317 details = "无法获取有效延迟数据" 318 avgLatency = 0 319 } 320 321 return TestResult{ 322 Test: "网络延迟检测", 323 Status: resultStatus, 324 StatusText: statusText, 325 Details: details, 326 IPv6Addresses: aaaaResult.IPv6Addresses, 327 AdditionalData: map[string]interface{}{ 328 "latency_results": latencyResults, 329 "average_latency": avgLatency, 330 }, 331 } 332} 333 334// generateSummary 生成检测总结 335func (t *IPv6CheckTool) generateSummary(tests []TestResult) map[string]interface{} { 336 successCount := 0 337 warningCount := 0 338 errorCount := 0 339 340 for _, test := range tests { 341 switch test.Status { 342 case "success": 343 successCount++ 344 case "warning": 345 warningCount++ 346 case "error": 347 errorCount++ 348 } 349 } 350 351 totalCount := len(tests) 352 var status, title, message string 353 354 if successCount == totalCount { 355 status = "success" 356 title = "IPv6支持良好" 357 message = fmt.Sprintf("所有 %d 个检测项目都通过,该网站完全支持IPv6访问。", totalCount) 358 } else if successCount > 0 || warningCount > 0 { 359 status = "warning" 360 title = "IPv6部分支持" 361 message = fmt.Sprintf("%d 个项目通过,%d 个项目警告,%d 个项目失败。该网站对IPv6的支持有限。", successCount, warningCount, errorCount) 362 } else { 363 status = "error" 364 title = "IPv6不支持" 365 message = fmt.Sprintf("所有 %d 个检测项目都失败,该网站不支持IPv6访问。", totalCount) 366 } 367 368 return map[string]interface{}{ 369 "status": status, 370 "title": title, 371 "message": message, 372 "statistics": map[string]int{ 373 "total": totalCount, 374 "success": successCount, 375 "warning": warningCount, 376 "error": errorCount, 377 }, 378 } 379} 380 381// BatchCheck 批量检测多个域名 382func (t *IPv6CheckTool) BatchCheck(domains []string, options CheckOptions) map[string]interface{} { 383 results := make(map[string]interface{}) 384 var mu sync.Mutex 385 var wg sync.WaitGroup 386 387 // 限制并发数 388 semaphore := make(chan struct{}, 5) 389 390 for _, domain := range domains { 391 wg.Add(1) 392 go func(d string) { 393 defer wg.Done() 394 semaphore <- struct{}{} 395 defer func() { <-semaphore }() 396 397 result, err := t.CheckIPv6Support(d, options) 398 mu.Lock() 399 if err != nil { 400 results[d] = map[string]interface{}{ 401 "error": err.Error(), 402 "domain": d, 403 "timestamp": time.Now().Format("2006-01-02 15:04:05"), 404 } 405 } else { 406 results[d] = result 407 } 408 mu.Unlock() 409 }(domain) 410 } 411 412 wg.Wait() 413 return results 414} 415 416// IsValidIPv6 验证IPv6地址格式 417func (t *IPv6CheckTool) IsValidIPv6(ipv6 string) bool { 418 ip := net.ParseIP(ipv6) 419 return ip != nil && ip.To4() == nil && ip.To16() != nil 420} 421 422// 使用示例 423func main() { 424 ipv6Tool := NewIPv6CheckTool() 425 426 // 单个域名检测 427 fmt.Println("检测单个域名:") 428 result, err := ipv6Tool.CheckIPv6Support("google.com", CheckOptions{ 429 CheckAAAA: true, 430 CheckConnectivity: true, 431 CheckDNS: true, 432 CheckLatency: true, 433 }) 434 435 if err != nil { 436 fmt.Printf("检测失败: %v\n", err) 437 return 438 } 439 440 jsonData, _ := json.MarshalIndent(result, "", " ") 441 fmt.Println(string(jsonData)) 442 443 // 批量检测 444 fmt.Println("\n批量检测:") 445 batchResults := ipv6Tool.BatchCheck([]string{"google.com", "github.com", "facebook.com"}, CheckOptions{ 446 CheckAAAA: true, 447 CheckConnectivity: false, 448 }) 449 450 jsonData, _ = json.MarshalIndent(batchResults, "", " ") 451 fmt.Println(string(jsonData)) 452}
-
ipv6_check (JAVA)
1import java.io.IOException; 2import java.net.InetAddress; 3import java.net.InetSocketAddress; 4import java.net.Socket; 5import java.net.UnknownHostException; 6import java.time.LocalDateTime; 7import java.time.format.DateTimeFormatter; 8import java.util.*; 9import java.util.concurrent.*; 10 11/** 12 * IPv6检测工具 - Java实现 13 * 检测网站是否支持IPv6访问 14 */ 15public class IPv6CheckTool { 16 17 private final List<String> defaultNameservers; 18 private final int timeout; 19 20 public IPv6CheckTool() { 21 this.defaultNameservers = Arrays.asList( 22 "2001:4860:4860::8888", // Google DNS IPv6 23 "2001:4860:4860::8844", // Google DNS IPv6备用 24 "2606:4700:4700::1111", // Cloudflare DNS IPv6 25 "2606:4700:4700::1001" // Cloudflare DNS IPv6备用 26 ); 27 this.timeout = 10000; // 10秒 28 } 29 30 /** 31 * 测试结果类 32 */ 33 public static class TestResult { 34 private String test; 35 private String status; 36 private String statusText; 37 private String details; 38 private List<String> ipv6Addresses; 39 private Map<String, Object> additionalData; 40 41 public TestResult(String test, String status, String statusText, String details) { 42 this.test = test; 43 this.status = status; 44 this.statusText = statusText; 45 this.details = details; 46 this.ipv6Addresses = new ArrayList<>(); 47 this.additionalData = new HashMap<>(); 48 } 49 50 // Getters and Setters 51 public String getTest() { return test; } 52 public void setTest(String test) { this.test = test; } 53 54 public String getStatus() { return status; } 55 public void setStatus(String status) { this.status = status; } 56 57 public String getStatusText() { return statusText; } 58 public void setStatusText(String statusText) { this.statusText = statusText; } 59 60 public String getDetails() { return details; } 61 public void setDetails(String details) { this.details = details; } 62 63 public List<String> getIpv6Addresses() { return ipv6Addresses; } 64 public void setIpv6Addresses(List<String> ipv6Addresses) { this.ipv6Addresses = ipv6Addresses; } 65 66 public Map<String, Object> getAdditionalData() { return additionalData; } 67 public void setAdditionalData(Map<String, Object> additionalData) { this.additionalData = additionalData; } 68 } 69 70 /** 71 * 检测结果类 72 */ 73 public static class CheckResult { 74 private String domain; 75 private String timestamp; 76 private List<TestResult> tests; 77 private Map<String, Object> summary; 78 79 public CheckResult(String domain) { 80 this.domain = domain; 81 this.timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); 82 this.tests = new ArrayList<>(); 83 this.summary = new HashMap<>(); 84 } 85 86 // Getters and Setters 87 public String getDomain() { return domain; } 88 public void setDomain(String domain) { this.domain = domain; } 89 90 public String getTimestamp() { return timestamp; } 91 public void setTimestamp(String timestamp) { this.timestamp = timestamp; } 92 93 public List<TestResult> getTests() { return tests; } 94 public void setTests(List<TestResult> tests) { this.tests = tests; } 95 96 public Map<String, Object> getSummary() { return summary; } 97 public void setSummary(Map<String, Object> summary) { this.summary = summary; } 98 } 99 100 /** 101 * 检测选项类 102 */ 103 public static class CheckOptions { 104 private boolean checkAAAA = true; 105 private boolean checkConnectivity = true; 106 private boolean checkDNS = true; 107 private boolean checkLatency = true; 108 109 public CheckOptions() {} 110 111 public CheckOptions(boolean checkAAAA, boolean checkConnectivity, boolean checkDNS, boolean checkLatency) { 112 this.checkAAAA = checkAAAA; 113 this.checkConnectivity = checkConnectivity; 114 this.checkDNS = checkDNS; 115 this.checkLatency = checkLatency; 116 } 117 118 // Getters and Setters 119 public boolean isCheckAAAA() { return checkAAAA; } 120 public void setCheckAAAA(boolean checkAAAA) { this.checkAAAA = checkAAAA; } 121 122 public boolean isCheckConnectivity() { return checkConnectivity; } 123 public void setCheckConnectivity(boolean checkConnectivity) { this.checkConnectivity = checkConnectivity; } 124 125 public boolean isCheckDNS() { return checkDNS; } 126 public void setCheckDNS(boolean checkDNS) { this.checkDNS = checkDNS; } 127 128 public boolean isCheckLatency() { return checkLatency; } 129 public void setCheckLatency(boolean checkLatency) { this.checkLatency = checkLatency; } 130 } 131 132 /** 133 * 检测域名的IPv6支持情况 134 */ 135 public CheckResult checkIPv6Support(String domain, CheckOptions options) { 136 CheckResult result = new CheckResult(domain); 137 138 try { 139 // 检测AAAA记录 140 if (options.isCheckAAAA()) { 141 TestResult aaaaResult = checkAAAARecord(domain); 142 result.getTests().add(aaaaResult); 143 } 144 145 // 检测IPv6连通性 146 if (options.isCheckConnectivity()) { 147 TestResult connectivityResult = checkIPv6Connectivity(domain); 148 result.getTests().add(connectivityResult); 149 } 150 151 // 检测DNS解析 152 if (options.isCheckDNS()) { 153 TestResult dnsResult = checkDNSResolution(domain); 154 result.getTests().add(dnsResult); 155 } 156 157 // 检测网络延迟 158 if (options.isCheckLatency()) { 159 TestResult latencyResult = checkLatency(domain); 160 result.getTests().add(latencyResult); 161 } 162 163 // 生成总结 164 result.setSummary(generateSummary(result.getTests())); 165 166 } catch (Exception e) { 167 System.err.println("IPv6检测失败: " + e.getMessage()); 168 throw new RuntimeException(e); 169 } 170 171 return result; 172 } 173 174 /** 175 * 检测AAAA记录 176 */ 177 private TestResult checkAAAARecord(String domain) { 178 List<String> ipv6Addresses = new ArrayList<>(); 179 180 try { 181 // 使用InetAddress查询IPv6地址 182 InetAddress[] addresses = InetAddress.getAllByName(domain); 183 for (InetAddress address : addresses) { 184 if (address.getHostAddress().contains(":")) { // IPv6地址包含冒号 185 ipv6Addresses.add(address.getHostAddress()); 186 } 187 } 188 189 if (!ipv6Addresses.isEmpty()) { 190 TestResult result = new TestResult( 191 "AAAA记录检测", 192 "success", 193 "支持", 194 "找到 " + ipv6Addresses.size() + " 个IPv6地址记录" 195 ); 196 result.setIpv6Addresses(ipv6Addresses); 197 return result; 198 } else { 199 TestResult result = new TestResult( 200 "AAAA记录检测", 201 "error", 202 "不支持", 203 "域名未配置IPv6地址记录" 204 ); 205 result.setIpv6Addresses(new ArrayList<>()); 206 return result; 207 } 208 209 } catch (UnknownHostException e) { 210 TestResult result = new TestResult( 211 "AAAA记录检测", 212 "error", 213 "检测失败", 214 "DNS查询失败: " + e.getMessage() 215 ); 216 result.setIpv6Addresses(new ArrayList<>()); 217 return result; 218 } 219 } 220 221 /** 222 * 检测IPv6连通性 223 */ 224 private TestResult checkIPv6Connectivity(String domain) { 225 // 首先获取IPv6地址 226 TestResult aaaaResult = checkAAAARecord(domain); 227 228 if ("error".equals(aaaaResult.getStatus())) { 229 TestResult result = new TestResult( 230 "IPv6连通性检测", 231 "error", 232 "无法检测", 233 "无法获取IPv6地址进行连通性检测" 234 ); 235 result.setIpv6Addresses(new ArrayList<>()); 236 return result; 237 } 238 239 // 测试IPv6地址连通性 240 List<Map<String, Object>> connectivityResults = new ArrayList<>(); 241 int reachableCount = 0; 242 243 for (String ipv6Address : aaaaResult.getIpv6Addresses()) { 244 long startTime = System.currentTimeMillis(); 245 boolean reachable = false; 246 long latency = 0; 247 248 try (Socket socket = new Socket()) { 249 socket.connect(new InetSocketAddress(ipv6Address, 80), 5000); 250 reachable = true; 251 latency = System.currentTimeMillis() - startTime; 252 reachableCount++; 253 } catch (IOException e) { 254 // 连接失败 255 } 256 257 Map<String, Object> result = new HashMap<>(); 258 result.put("ipv6_address", ipv6Address); 259 result.put("reachable", reachable); 260 result.put("latency", latency); 261 connectivityResults.add(result); 262 } 263 264 int totalCount = connectivityResults.size(); 265 266 if (reachableCount == totalCount) { 267 TestResult result = new TestResult( 268 "IPv6连通性检测", 269 "success", 270 "完全可达", 271 "所有 " + totalCount + " 个IPv6地址都可以访问" 272 ); 273 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 274 result.getAdditionalData().put("connectivity_results", connectivityResults); 275 return result; 276 } else if (reachableCount > 0) { 277 TestResult result = new TestResult( 278 "IPv6连通性检测", 279 "warning", 280 "部分可达", 281 reachableCount + "/" + totalCount + " 个IPv6地址可以访问" 282 ); 283 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 284 result.getAdditionalData().put("connectivity_results", connectivityResults); 285 return result; 286 } else { 287 TestResult result = new TestResult( 288 "IPv6连通性检测", 289 "error", 290 "不可达", 291 "所有IPv6地址都无法访问" 292 ); 293 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 294 result.getAdditionalData().put("connectivity_results", connectivityResults); 295 return result; 296 } 297 } 298 299 /** 300 * 检测DNS解析 301 */ 302 private TestResult checkDNSResolution(String domain) { 303 List<String> ipv6Addresses = new ArrayList<>(); 304 305 try { 306 // 使用InetAddress查询IPv6地址 307 InetAddress[] addresses = InetAddress.getAllByName(domain); 308 for (InetAddress address : addresses) { 309 if (address.getHostAddress().contains(":")) { // IPv6地址包含冒号 310 ipv6Addresses.add(address.getHostAddress()); 311 } 312 } 313 314 if (!ipv6Addresses.isEmpty()) { 315 TestResult result = new TestResult( 316 "DNS解析检测", 317 "success", 318 "正常", 319 "IPv6 DNS解析正常" 320 ); 321 result.setIpv6Addresses(ipv6Addresses); 322 return result; 323 } else { 324 TestResult result = new TestResult( 325 "DNS解析检测", 326 "warning", 327 "部分正常", 328 "IPv6 DNS解析部分正常" 329 ); 330 result.setIpv6Addresses(new ArrayList<>()); 331 return result; 332 } 333 334 } catch (UnknownHostException e) { 335 TestResult result = new TestResult( 336 "DNS解析检测", 337 "error", 338 "异常", 339 "DNS解析异常: " + e.getMessage() 340 ); 341 result.setIpv6Addresses(new ArrayList<>()); 342 return result; 343 } 344 } 345 346 /** 347 * 检测网络延迟 348 */ 349 private TestResult checkLatency(String domain) { 350 // 获取IPv6地址 351 TestResult aaaaResult = checkAAAARecord(domain); 352 353 if ("error".equals(aaaaResult.getStatus())) { 354 TestResult result = new TestResult( 355 "网络延迟检测", 356 "error", 357 "无法检测", 358 "无法获取IPv6地址进行延迟检测" 359 ); 360 result.setIpv6Addresses(new ArrayList<>()); 361 return result; 362 } 363 364 // 测试延迟 365 List<Map<String, Object>> latencyResults = new ArrayList<>(); 366 double totalLatency = 0; 367 int validCount = 0; 368 369 for (String ipv6Address : aaaaResult.getIpv6Addresses()) { 370 long startTime = System.currentTimeMillis(); 371 double latency = 0; 372 String status; 373 374 try (Socket socket = new Socket()) { 375 socket.connect(new InetSocketAddress(ipv6Address, 80), 5000); 376 latency = System.currentTimeMillis() - startTime; 377 totalLatency += latency; 378 validCount++; 379 380 if (latency < 100) { 381 status = "excellent"; 382 } else if (latency < 200) { 383 status = "good"; 384 } else { 385 status = "poor"; 386 } 387 } catch (IOException e) { 388 latency = 0; 389 status = "failed"; 390 } 391 392 Map<String, Object> result = new HashMap<>(); 393 result.put("ipv6_address", ipv6Address); 394 result.put("latency", latency); 395 result.put("status", status); 396 latencyResults.add(result); 397 } 398 399 double avgLatency = 0; 400 String resultStatus, statusText, details; 401 402 if (validCount > 0) { 403 avgLatency = totalLatency / validCount; 404 if (avgLatency < 100) { 405 resultStatus = "success"; 406 statusText = "优秀"; 407 } else if (avgLatency < 200) { 408 resultStatus = "warning"; 409 statusText = "良好"; 410 } else { 411 resultStatus = "error"; 412 statusText = "较差"; 413 } 414 details = String.format("平均延迟: %.1fms", avgLatency); 415 } else { 416 resultStatus = "error"; 417 statusText = "检测失败"; 418 details = "无法获取有效延迟数据"; 419 avgLatency = 0; 420 } 421 422 TestResult result = new TestResult( 423 "网络延迟检测", 424 resultStatus, 425 statusText, 426 details 427 ); 428 result.setIpv6Addresses(aaaaResult.getIpv6Addresses()); 429 result.getAdditionalData().put("latency_results", latencyResults); 430 result.getAdditionalData().put("average_latency", avgLatency); 431 432 return result; 433 } 434 435 /** 436 * 生成检测总结 437 */ 438 private Map<String, Object> generateSummary(List<TestResult> tests) { 439 int successCount = 0; 440 int warningCount = 0; 441 int errorCount = 0; 442 443 for (TestResult test : tests) { 444 switch (test.getStatus()) { 445 case "success": 446 successCount++; 447 break; 448 case "warning": 449 warningCount++; 450 break; 451 case "error": 452 errorCount++; 453 break; 454 } 455 } 456 457 int totalCount = tests.size(); 458 String status, title, message; 459 460 if (successCount == totalCount) { 461 status = "success"; 462 title = "IPv6支持良好"; 463 message = "所有 " + totalCount + " 个检测项目都通过,该网站完全支持IPv6访问。"; 464 } else if (successCount > 0 || warningCount > 0) { 465 status = "warning"; 466 title = "IPv6部分支持"; 467 message = successCount + " 个项目通过," + warningCount + " 个项目警告," + errorCount + " 个项目失败。该网站对IPv6的支持有限。"; 468 } else { 469 status = "error"; 470 title = "IPv6不支持"; 471 message = "所有 " + totalCount + " 个检测项目都失败,该网站不支持IPv6访问。"; 472 } 473 474 Map<String, Object> summary = new HashMap<>(); 475 summary.put("status", status); 476 summary.put("title", title); 477 summary.put("message", message); 478 479 Map<String, Integer> statistics = new HashMap<>(); 480 statistics.put("total", totalCount); 481 statistics.put("success", successCount); 482 statistics.put("warning", warningCount); 483 statistics.put("error", errorCount); 484 summary.put("statistics", statistics); 485 486 return summary; 487 } 488 489 /** 490 * 批量检测多个域名 491 */ 492 public Map<String, Object> batchCheck(List<String> domains, CheckOptions options) { 493 Map<String, Object> results = new HashMap<>(); 494 ExecutorService executor = Executors.newFixedThreadPool(5); 495 496 try { 497 List<Future<Map.Entry<String, Object>>> futures = new ArrayList<>(); 498 499 for (String domain : domains) { 500 Future<Map.Entry<String, Object>> future = executor.submit(() -> { 501 try { 502 CheckResult result = checkIPv6Support(domain, options); 503 return new AbstractMap.SimpleEntry<>(domain, result); 504 } catch (Exception e) { 505 Map<String, Object> errorResult = new HashMap<>(); 506 errorResult.put("error", e.getMessage()); 507 errorResult.put("domain", domain); 508 errorResult.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); 509 return new AbstractMap.SimpleEntry<>(domain, errorResult); 510 } 511 }); 512 futures.add(future); 513 } 514 515 for (Future<Map.Entry<String, Object>> future : futures) { 516 try { 517 Map.Entry<String, Object> entry = future.get(); 518 results.put(entry.getKey(), entry.getValue()); 519 } catch (Exception e) { 520 System.err.println("批量检测失败: " + e.getMessage()); 521 } 522 } 523 524 } finally { 525 executor.shutdown(); 526 } 527 528 return results; 529 } 530 531 /** 532 * 验证IPv6地址格式 533 */ 534 public boolean isValidIPv6(String ipv6) { 535 try { 536 InetAddress.getByName(ipv6); 537 return ipv6.contains(":"); 538 } catch (UnknownHostException e) { 539 return false; 540 } 541 } 542 543 /** 544 * 使用示例 545 */ 546 public static void main(String[] args) { 547 IPv6CheckTool ipv6Tool = new IPv6CheckTool(); 548 549 try { 550 // 单个域名检测 551 System.out.println("检测单个域名:"); 552 CheckResult result = ipv6Tool.checkIPv6Support("google.com", new CheckOptions(true, true, true, true)); 553 System.out.println("域名: " + result.getDomain()); 554 System.out.println("时间: " + result.getTimestamp()); 555 System.out.println("测试数量: " + result.getTests().size()); 556 System.out.println("总结: " + result.getSummary()); 557 558 // 批量检测 559 System.out.println("\n批量检测:"); 560 List<String> domains = Arrays.asList("google.com", "github.com", "facebook.com"); 561 Map<String, Object> batchResults = ipv6Tool.batchCheck(domains, new CheckOptions(true, false, true, false)); 562 System.out.println("批量检测结果: " + batchResults.size() + " 个域名"); 563 564 } catch (Exception e) { 565 System.err.println("检测失败: " + e.getMessage()); 566 } 567 } 568}
-
ipv6_check (JS)
1/** 2 * IPv6检测工具 - JavaScript实现 3 * 检测网站是否支持IPv6访问 4 */ 5 6class IPv6CheckTool { 7 constructor() { 8 this.defaultNameservers = [ 9 '2001:4860:4860::8888', // Google DNS IPv6 10 '2001:4860:4860::8844', // Google DNS IPv6备用 11 '2606:4700:4700::1111', // Cloudflare DNS IPv6 12 '2606:4700:4700::1001' // Cloudflare DNS IPv6备用 13 ]; 14 } 15 16 /** 17 * 检测域名的IPv6支持情况 18 * @param {string} domain - 域名 19 * @param {Object} options - 检测选项 20 * @returns {Promise<Object>} 检测结果 21 */ 22 async checkIPv6Support(domain, options = {}) { 23 const { 24 checkAAAA = true, 25 checkConnectivity = true, 26 checkDNS = true, 27 checkLatency = true 28 } = options; 29 30 const results = { 31 domain: domain, 32 timestamp: new Date().toISOString(), 33 tests: [] 34 }; 35 36 try { 37 // 检测AAAA记录 38 if (checkAAAA) { 39 const aaaaResult = await this.checkAAAARecord(domain); 40 results.tests.push(aaaaResult); 41 } 42 43 // 检测IPv6连通性 44 if (checkConnectivity) { 45 const connectivityResult = await this.checkIPv6Connectivity(domain); 46 results.tests.push(connectivityResult); 47 } 48 49 // 检测DNS解析 50 if (checkDNS) { 51 const dnsResult = await this.checkDNSResolution(domain); 52 results.tests.push(dnsResult); 53 } 54 55 // 检测网络延迟 56 if (checkLatency) { 57 const latencyResult = await this.checkLatency(domain); 58 results.tests.push(latencyResult); 59 } 60 61 // 生成总结 62 results.summary = this.generateSummary(results.tests); 63 64 } catch (error) { 65 console.error('IPv6检测失败:', error); 66 throw error; 67 } 68 69 return results; 70 } 71 72 /** 73 * 检测AAAA记录 74 * @param {string} domain - 域名 75 * @returns {Promise<Object>} 检测结果 76 */ 77 async checkAAAARecord(domain) { 78 try { 79 // 使用DNS API查询AAAA记录 80 const response = await fetch(`https://cloudflare-dns.com/dns-query?name=${domain}&type=AAAA`, { 81 method: 'GET', 82 headers: { 83 'Accept': 'application/dns-json' 84 } 85 }); 86 87 const data = await response.json(); 88 89 if (data.Status === 0 && data.Answer && data.Answer.length > 0) { 90 const ipv6Addresses = data.Answer.map(answer => answer.data); 91 return { 92 test: 'AAAA记录检测', 93 status: 'success', 94 statusText: '支持', 95 details: `找到 ${ipv6Addresses.length} 个IPv6地址记录`, 96 ipv6Addresses: ipv6Addresses, 97 ttl: data.Answer[0].TTL 98 }; 99 } else { 100 return { 101 test: 'AAAA记录检测', 102 status: 'error', 103 statusText: '不支持', 104 details: '域名未配置IPv6地址记录', 105 ipv6Addresses: [], 106 ttl: null 107 }; 108 } 109 } catch (error) { 110 return { 111 test: 'AAAA记录检测', 112 status: 'error', 113 statusText: '检测失败', 114 details: `DNS查询失败: ${error.message}`, 115 ipv6Addresses: [], 116 ttl: null 117 }; 118 } 119 } 120 121 /** 122 * 检测IPv6连通性 123 * @param {string} domain - 域名 124 * @returns {Promise<Object>} 检测结果 125 */ 126 async checkIPv6Connectivity(domain) { 127 try { 128 // 首先获取IPv6地址 129 const aaaaResult = await this.checkAAAARecord(domain); 130 131 if (aaaaResult.status === 'error') { 132 return { 133 test: 'IPv6连通性检测', 134 status: 'error', 135 statusText: '无法检测', 136 details: '无法获取IPv6地址进行连通性检测', 137 ipv6Addresses: [], 138 latency: null 139 }; 140 } 141 142 // 测试IPv6地址连通性 143 const connectivityResults = []; 144 for (const ipv6Address of aaaaResult.ipv6Addresses) { 145 try { 146 const startTime = Date.now(); 147 const response = await fetch(`https://[${ipv6Address}]/`, { 148 method: 'HEAD', 149 mode: 'no-cors', 150 timeout: 5000 151 }); 152 const latency = Date.now() - startTime; 153 154 connectivityResults.push({ 155 ipv6Address: ipv6Address, 156 reachable: true, 157 latency: latency 158 }); 159 } catch (error) { 160 connectivityResults.push({ 161 ipv6Address: ipv6Address, 162 reachable: false, 163 latency: null, 164 error: error.message 165 }); 166 } 167 } 168 169 const reachableCount = connectivityResults.filter(r => r.reachable).length; 170 const totalCount = connectivityResults.length; 171 172 if (reachableCount === totalCount) { 173 return { 174 test: 'IPv6连通性检测', 175 status: 'success', 176 statusText: '完全可达', 177 details: `所有 ${totalCount} 个IPv6地址都可以访问`, 178 ipv6Addresses: aaaaResult.ipv6Addresses, 179 connectivityResults: connectivityResults 180 }; 181 } else if (reachableCount > 0) { 182 return { 183 test: 'IPv6连通性检测', 184 status: 'warning', 185 statusText: '部分可达', 186 details: `${reachableCount}/${totalCount} 个IPv6地址可以访问`, 187 ipv6Addresses: aaaaResult.ipv6Addresses, 188 connectivityResults: connectivityResults 189 }; 190 } else { 191 return { 192 test: 'IPv6连通性检测', 193 status: 'error', 194 statusText: '不可达', 195 details: '所有IPv6地址都无法访问', 196 ipv6Addresses: aaaaResult.ipv6Addresses, 197 connectivityResults: connectivityResults 198 }; 199 } 200 } catch (error) { 201 return { 202 test: 'IPv6连通性检测', 203 status: 'error', 204 statusText: '检测失败', 205 details: `连通性检测失败: ${error.message}`, 206 ipv6Addresses: [], 207 connectivityResults: [] 208 }; 209 } 210 } 211 212 /** 213 * 检测DNS解析 214 * @param {string} domain - 域名 215 * @returns {Promise<Object>} 检测结果 216 */ 217 async checkDNSResolution(domain) { 218 try { 219 // 检测IPv6 DNS解析 220 const response = await fetch(`https://cloudflare-dns.com/dns-query?name=${domain}&type=AAAA`, { 221 method: 'GET', 222 headers: { 223 'Accept': 'application/dns-json' 224 } 225 }); 226 227 const data = await response.json(); 228 229 if (data.Status === 0) { 230 return { 231 test: 'DNS解析检测', 232 status: 'success', 233 statusText: '正常', 234 details: 'IPv6 DNS解析正常', 235 ipv6Addresses: data.Answer ? data.Answer.map(a => a.data) : [], 236 authority: data.Authority || [] 237 }; 238 } else { 239 return { 240 test: 'DNS解析检测', 241 status: 'warning', 242 statusText: '部分正常', 243 details: `DNS解析状态: ${data.Status}`, 244 ipv6Addresses: [], 245 authority: data.Authority || [] 246 }; 247 } 248 } catch (error) { 249 return { 250 test: 'DNS解析检测', 251 status: 'error', 252 statusText: '异常', 253 details: `DNS解析异常: ${error.message}`, 254 ipv6Addresses: [], 255 authority: [] 256 }; 257 } 258 } 259 260 /** 261 * 检测网络延迟 262 * @param {string} domain - 域名 263 * @returns {Promise<Object>} 检测结果 264 */ 265 async checkLatency(domain) { 266 try { 267 // 获取IPv6地址 268 const aaaaResult = await this.checkAAAARecord(domain); 269 270 if (aaaaResult.status === 'error') { 271 return { 272 test: '网络延迟检测', 273 status: 'error', 274 statusText: '无法检测', 275 details: '无法获取IPv6地址进行延迟检测', 276 ipv6Addresses: [], 277 latencyResults: [] 278 }; 279 } 280 281 // 测试延迟 282 const latencyResults = []; 283 for (const ipv6Address of aaaaResult.ipv6Addresses) { 284 try { 285 const startTime = Date.now(); 286 await fetch(`https://[${ipv6Address}]/`, { 287 method: 'HEAD', 288 mode: 'no-cors', 289 timeout: 5000 290 }); 291 const latency = Date.now() - startTime; 292 293 latencyResults.push({ 294 ipv6Address: ipv6Address, 295 latency: latency, 296 status: latency < 100 ? 'excellent' : latency < 200 ? 'good' : 'poor' 297 }); 298 } catch (error) { 299 latencyResults.push({ 300 ipv6Address: ipv6Address, 301 latency: null, 302 status: 'failed', 303 error: error.message 304 }); 305 } 306 } 307 308 const avgLatency = latencyResults 309 .filter(r => r.latency !== null) 310 .reduce((sum, r) => sum + r.latency, 0) / 311 latencyResults.filter(r => r.latency !== null).length; 312 313 return { 314 test: '网络延迟检测', 315 status: avgLatency < 100 ? 'success' : avgLatency < 200 ? 'warning' : 'error', 316 statusText: avgLatency < 100 ? '优秀' : avgLatency < 200 ? '良好' : '较差', 317 details: `平均延迟: ${Math.round(avgLatency)}ms`, 318 ipv6Addresses: aaaaResult.ipv6Addresses, 319 latencyResults: latencyResults, 320 averageLatency: avgLatency 321 }; 322 } catch (error) { 323 return { 324 test: '网络延迟检测', 325 status: 'error', 326 statusText: '检测失败', 327 details: `延迟检测失败: ${error.message}`, 328 ipv6Addresses: [], 329 latencyResults: [] 330 }; 331 } 332 } 333 334 /** 335 * 生成检测总结 336 * @param {Array} tests - 检测结果数组 337 * @returns {Object} 总结信息 338 */ 339 generateSummary(tests) { 340 const successCount = tests.filter(t => t.status === 'success').length; 341 const warningCount = tests.filter(t => t.status === 'warning').length; 342 const errorCount = tests.filter(t => t.status === 'error').length; 343 const totalCount = tests.length; 344 345 let status, title, message; 346 347 if (successCount === totalCount) { 348 status = 'success'; 349 title = 'IPv6支持良好'; 350 message = `所有 ${totalCount} 个检测项目都通过,该网站完全支持IPv6访问。`; 351 } else if (successCount > 0 || warningCount > 0) { 352 status = 'warning'; 353 title = 'IPv6部分支持'; 354 message = `${successCount} 个项目通过,${warningCount} 个项目警告,${errorCount} 个项目失败。该网站对IPv6的支持有限。`; 355 } else { 356 status = 'error'; 357 title = 'IPv6不支持'; 358 message = `所有 ${totalCount} 个检测项目都失败,该网站不支持IPv6访问。`; 359 } 360 361 return { 362 status: status, 363 title: title, 364 message: message, 365 statistics: { 366 total: totalCount, 367 success: successCount, 368 warning: warningCount, 369 error: errorCount 370 } 371 }; 372 } 373 374 /** 375 * 批量检测多个域名 376 * @param {Array} domains - 域名数组 377 * @param {Object} options - 检测选项 378 * @returns {Promise<Object>} 批量检测结果 379 */ 380 async batchCheck(domains, options = {}) { 381 const results = {}; 382 383 for (const domain of domains) { 384 try { 385 results[domain] = await this.checkIPv6Support(domain, options); 386 } catch (error) { 387 results[domain] = { 388 error: error.message, 389 domain: domain, 390 timestamp: new Date().toISOString() 391 }; 392 } 393 } 394 395 return results; 396 } 397 398 /** 399 * 验证IPv6地址格式 400 * @param {string} ipv6 - IPv6地址 401 * @returns {boolean} 是否为有效IPv6地址 402 */ 403 isValidIPv6(ipv6) { 404 const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::1$|^::$/; 405 return ipv6Regex.test(ipv6); 406 } 407} 408 409// 使用示例 410async function example() { 411 const ipv6Tool = new IPv6CheckTool(); 412 413 try { 414 // 单个域名检测 415 console.log('检测单个域名:'); 416 const result = await ipv6Tool.checkIPv6Support('google.com', { 417 checkAAAA: true, 418 checkConnectivity: true, 419 checkDNS: true, 420 checkLatency: true 421 }); 422 console.log(JSON.stringify(result, null, 2)); 423 424 // 批量检测 425 console.log('\n批量检测:'); 426 const batchResults = await ipv6Tool.batchCheck(['google.com', 'github.com', 'facebook.com'], { 427 checkAAAA: true, 428 checkConnectivity: false 429 }); 430 console.log(JSON.stringify(batchResults, null, 2)); 431 432 } catch (error) { 433 console.error('检测失败:', error); 434 } 435} 436 437// 导出类 438if (typeof module !== 'undefined' && module.exports) { 439 module.exports = IPv6CheckTool; 440}
-
ipv6_check (PHP)
1<?php 2/** 3 * IPv6检测工具 - PHP实现 4 * 检测网站是否支持IPv6访问 5 */ 6 7class IPv6CheckTool { 8 private $defaultNameservers; 9 private $timeout; 10 11 public function __construct() { 12 $this->defaultNameservers = [ 13 '2001:4860:4860::8888', // Google DNS IPv6 14 '2001:4860:4860::8844', // Google DNS IPv6备用 15 '2606:4700:4700::1111', // Cloudflare DNS IPv6 16 '2606:4700:4700::1001' // Cloudflare DNS IPv6备用 17 ]; 18 $this->timeout = 10; // 10秒 19 } 20 21 /** 22 * 检测域名的IPv6支持情况 23 * 24 * @param string $domain 域名 25 * @param array $options 检测选项 26 * @return array 检测结果 27 */ 28 public function checkIPv6Support($domain, $options = []) { 29 $checkAAAA = $options['check_aaaa'] ?? true; 30 $checkConnectivity = $options['check_connectivity'] ?? true; 31 $checkDNS = $options['check_dns'] ?? true; 32 $checkLatency = $options['check_latency'] ?? true; 33 34 $results = [ 35 'domain' => $domain, 36 'timestamp' => date('Y-m-d H:i:s'), 37 'tests' => [] 38 ]; 39 40 try { 41 // 检测AAAA记录 42 if ($checkAAAA) { 43 $aaaaResult = $this->checkAAAARecord($domain); 44 $results['tests'][] = $aaaaResult; 45 } 46 47 // 检测IPv6连通性 48 if ($checkConnectivity) { 49 $connectivityResult = $this->checkIPv6Connectivity($domain); 50 $results['tests'][] = $connectivityResult; 51 } 52 53 // 检测DNS解析 54 if ($checkDNS) { 55 $dnsResult = $this->checkDNSResolution($domain); 56 $results['tests'][] = $dnsResult; 57 } 58 59 // 检测网络延迟 60 if ($checkLatency) { 61 $latencyResult = $this->checkLatency($domain); 62 $results['tests'][] = $latencyResult; 63 } 64 65 // 生成总结 66 $results['summary'] = $this->generateSummary($results['tests']); 67 68 } catch (Exception $e) { 69 error_log("IPv6检测失败: " . $e->getMessage()); 70 throw $e; 71 } 72 73 return $results; 74 } 75 76 /** 77 * 检测AAAA记录 78 * 79 * @param string $domain 域名 80 * @return array 检测结果 81 */ 82 private function checkAAAARecord($domain) { 83 $ipv6Addresses = []; 84 85 try { 86 // 使用gethostbynamel查询IPv6地址 87 $ips = gethostbynamel($domain); 88 if ($ips !== false) { 89 foreach ($ips as $ip) { 90 if ($this->isValidIPv6($ip)) { 91 $ipv6Addresses[] = $ip; 92 } 93 } 94 } 95 96 // 尝试使用dns_get_record查询AAAA记录 97 $records = dns_get_record($domain, DNS_AAAA); 98 foreach ($records as $record) { 99 if (isset($record['ipv6'])) { 100 $ipv6Addresses[] = $record['ipv6']; 101 } 102 } 103 104 if (!empty($ipv6Addresses)) { 105 return [ 106 'test' => 'AAAA记录检测', 107 'status' => 'success', 108 'status_text' => '支持', 109 'details' => '找到 ' . count($ipv6Addresses) . ' 个IPv6地址记录', 110 'ipv6_addresses' => $ipv6Addresses 111 ]; 112 } else { 113 return [ 114 'test' => 'AAAA记录检测', 115 'status' => 'error', 116 'status_text' => '不支持', 117 'details' => '域名未配置IPv6地址记录', 118 'ipv6_addresses' => [] 119 ]; 120 } 121 122 } catch (Exception $e) { 123 return [ 124 'test' => 'AAAA记录检测', 125 'status' => 'error', 126 'status_text' => '检测失败', 127 'details' => 'DNS查询失败: ' . $e->getMessage(), 128 'ipv6_addresses' => [] 129 ]; 130 } 131 } 132 133 /** 134 * 检测IPv6连通性 135 * 136 * @param string $domain 域名 137 * @return array 检测结果 138 */ 139 private function checkIPv6Connectivity($domain) { 140 // 首先获取IPv6地址 141 $aaaaResult = $this->checkAAAARecord($domain); 142 143 if ($aaaaResult['status'] === 'error') { 144 return [ 145 'test' => 'IPv6连通性检测', 146 'status' => 'error', 147 'status_text' => '无法检测', 148 'details' => '无法获取IPv6地址进行连通性检测', 149 'ipv6_addresses' => [] 150 ]; 151 } 152 153 // 测试IPv6地址连通性 154 $connectivityResults = []; 155 $reachableCount = 0; 156 157 foreach ($aaaaResult['ipv6_addresses'] as $ipv6Address) { 158 $startTime = microtime(true); 159 $reachable = false; 160 $latency = 0; 161 162 try { 163 // 尝试连接IPv6地址 164 $context = stream_context_create([ 165 'socket' => [ 166 'bindto' => '::', 167 'timeout' => 5 168 ] 169 ]); 170 171 $socket = @stream_socket_client( 172 "tcp://[{$ipv6Address}]:80", 173 $errno, 174 $errstr, 175 5, 176 STREAM_CLIENT_CONNECT, 177 $context 178 ); 179 180 if ($socket !== false) { 181 fclose($socket); 182 $reachable = true; 183 $latency = (microtime(true) - $startTime) * 1000; 184 $reachableCount++; 185 } 186 } catch (Exception $e) { 187 // 连接失败 188 } 189 190 $connectivityResults[] = [ 191 'ipv6_address' => $ipv6Address, 192 'reachable' => $reachable, 193 'latency' => $latency 194 ]; 195 } 196 197 $totalCount = count($connectivityResults); 198 199 if ($reachableCount === $totalCount) { 200 return [ 201 'test' => 'IPv6连通性检测', 202 'status' => 'success', 203 'status_text' => '完全可达', 204 'details' => "所有 {$totalCount} 个IPv6地址都可以访问", 205 'ipv6_addresses' => $aaaaResult['ipv6_addresses'], 206 'additional_data' => [ 207 'connectivity_results' => $connectivityResults 208 ] 209 ]; 210 } elseif ($reachableCount > 0) { 211 return [ 212 'test' => 'IPv6连通性检测', 213 'status' => 'warning', 214 'status_text' => '部分可达', 215 'details' => "{$reachableCount}/{$totalCount} 个IPv6地址可以访问", 216 'ipv6_addresses' => $aaaaResult['ipv6_addresses'], 217 'additional_data' => [ 218 'connectivity_results' => $connectivityResults 219 ] 220 ]; 221 } else { 222 return [ 223 'test' => 'IPv6连通性检测', 224 'status' => 'error', 225 'status_text' => '不可达', 226 'details' => '所有IPv6地址都无法访问', 227 'ipv6_addresses' => $aaaaResult['ipv6_addresses'], 228 'additional_data' => [ 229 'connectivity_results' => $connectivityResults 230 ] 231 ]; 232 } 233 } 234 235 /** 236 * 检测DNS解析 237 * 238 * @param string $domain 域名 239 * @return array 检测结果 240 */ 241 private function checkDNSResolution($domain) { 242 $ipv6Addresses = []; 243 244 try { 245 // 使用gethostbynamel查询IPv6地址 246 $ips = gethostbynamel($domain); 247 if ($ips !== false) { 248 foreach ($ips as $ip) { 249 if ($this->isValidIPv6($ip)) { 250 $ipv6Addresses[] = $ip; 251 } 252 } 253 } 254 255 // 尝试使用dns_get_record查询AAAA记录 256 $records = dns_get_record($domain, DNS_AAAA); 257 foreach ($records as $record) { 258 if (isset($record['ipv6'])) { 259 $ipv6Addresses[] = $record['ipv6']; 260 } 261 } 262 263 if (!empty($ipv6Addresses)) { 264 return [ 265 'test' => 'DNS解析检测', 266 'status' => 'success', 267 'status_text' => '正常', 268 'details' => 'IPv6 DNS解析正常', 269 'ipv6_addresses' => $ipv6Addresses 270 ]; 271 } else { 272 return [ 273 'test' => 'DNS解析检测', 274 'status' => 'warning', 275 'status_text' => '部分正常', 276 'details' => 'IPv6 DNS解析部分正常', 277 'ipv6_addresses' => [] 278 ]; 279 } 280 281 } catch (Exception $e) { 282 return [ 283 'test' => 'DNS解析检测', 284 'status' => 'error', 285 'status_text' => '异常', 286 'details' => 'DNS解析异常: ' . $e->getMessage(), 287 'ipv6_addresses' => [] 288 ]; 289 } 290 } 291 292 /** 293 * 检测网络延迟 294 * 295 * @param string $domain 域名 296 * @return array 检测结果 297 */ 298 private function checkLatency($domain) { 299 // 获取IPv6地址 300 $aaaaResult = $this->checkAAAARecord($domain); 301 302 if ($aaaaResult['status'] === 'error') { 303 return [ 304 'test' => '网络延迟检测', 305 'status' => 'error', 306 'status_text' => '无法检测', 307 'details' => '无法获取IPv6地址进行延迟检测', 308 'ipv6_addresses' => [] 309 ]; 310 } 311 312 // 测试延迟 313 $latencyResults = []; 314 $totalLatency = 0; 315 $validCount = 0; 316 317 foreach ($aaaaResult['ipv6_addresses'] as $ipv6Address) { 318 $startTime = microtime(true); 319 $latency = 0; 320 $status = 'failed'; 321 322 try { 323 // 尝试连接IPv6地址 324 $context = stream_context_create([ 325 'socket' => [ 326 'bindto' => '::', 327 'timeout' => 5 328 ] 329 ]); 330 331 $socket = @stream_socket_client( 332 "tcp://[{$ipv6Address}]:80", 333 $errno, 334 $errstr, 335 5, 336 STREAM_CLIENT_CONNECT, 337 $context 338 ); 339 340 if ($socket !== false) { 341 fclose($socket); 342 $latency = (microtime(true) - $startTime) * 1000; 343 $totalLatency += $latency; 344 $validCount++; 345 346 if ($latency < 100) { 347 $status = 'excellent'; 348 } elseif ($latency < 200) { 349 $status = 'good'; 350 } else { 351 $status = 'poor'; 352 } 353 } 354 } catch (Exception $e) { 355 $latency = 0; 356 $status = 'failed'; 357 } 358 359 $latencyResults[] = [ 360 'ipv6_address' => $ipv6Address, 361 'latency' => $latency, 362 'status' => $status 363 ]; 364 } 365 366 if ($validCount > 0) { 367 $avgLatency = $totalLatency / $validCount; 368 if ($avgLatency < 100) { 369 $resultStatus = 'success'; 370 $statusText = '优秀'; 371 } elseif ($avgLatency < 200) { 372 $resultStatus = 'warning'; 373 $statusText = '良好'; 374 } else { 375 $resultStatus = 'error'; 376 $statusText = '较差'; 377 } 378 $details = sprintf('平均延迟: %.1fms', $avgLatency); 379 } else { 380 $resultStatus = 'error'; 381 $statusText = '检测失败'; 382 $details = '无法获取有效延迟数据'; 383 $avgLatency = 0; 384 } 385 386 return [ 387 'test' => '网络延迟检测', 388 'status' => $resultStatus, 389 'status_text' => $statusText, 390 'details' => $details, 391 'ipv6_addresses' => $aaaaResult['ipv6_addresses'], 392 'additional_data' => [ 393 'latency_results' => $latencyResults, 394 'average_latency' => $avgLatency 395 ] 396 ]; 397 } 398 399 /** 400 * 生成检测总结 401 * 402 * @param array $tests 检测结果数组 403 * @return array 总结信息 404 */ 405 private function generateSummary($tests) { 406 $successCount = 0; 407 $warningCount = 0; 408 $errorCount = 0; 409 410 foreach ($tests as $test) { 411 switch ($test['status']) { 412 case 'success': 413 $successCount++; 414 break; 415 case 'warning': 416 $warningCount++; 417 break; 418 case 'error': 419 $errorCount++; 420 break; 421 } 422 } 423 424 $totalCount = count($tests); 425 426 if ($successCount === $totalCount) { 427 $status = 'success'; 428 $title = 'IPv6支持良好'; 429 $message = "所有 {$totalCount} 个检测项目都通过,该网站完全支持IPv6访问。"; 430 } elseif ($successCount > 0 || $warningCount > 0) { 431 $status = 'warning'; 432 $title = 'IPv6部分支持'; 433 $message = "{$successCount} 个项目通过,{$warningCount} 个项目警告,{$errorCount} 个项目失败。该网站对IPv6的支持有限。"; 434 } else { 435 $status = 'error'; 436 $title = 'IPv6不支持'; 437 $message = "所有 {$totalCount} 个检测项目都失败,该网站不支持IPv6访问。"; 438 } 439 440 return [ 441 'status' => $status, 442 'title' => $title, 443 'message' => $message, 444 'statistics' => [ 445 'total' => $totalCount, 446 'success' => $successCount, 447 'warning' => $warningCount, 448 'error' => $errorCount 449 ] 450 ]; 451 } 452 453 /** 454 * 批量检测多个域名 455 * 456 * @param array $domains 域名数组 457 * @param array $options 检测选项 458 * @return array 批量检测结果 459 */ 460 public function batchCheck($domains, $options = []) { 461 $results = []; 462 463 foreach ($domains as $domain) { 464 try { 465 $results[$domain] = $this->checkIPv6Support($domain, $options); 466 } catch (Exception $e) { 467 $results[$domain] = [ 468 'error' => $e->getMessage(), 469 'domain' => $domain, 470 'timestamp' => date('Y-m-d H:i:s') 471 ]; 472 } 473 } 474 475 return $results; 476 } 477 478 /** 479 * 验证IPv6地址格式 480 * 481 * @param string $ipv6 IPv6地址 482 * @return bool 是否为有效IPv6地址 483 */ 484 public function isValidIPv6($ipv6) { 485 return filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false; 486 } 487} 488 489// 使用示例 490function example() { 491 $ipv6Tool = new IPv6CheckTool(); 492 493 try { 494 // 单个域名检测 495 echo "检测单个域名:\n"; 496 $result = $ipv6Tool->checkIPv6Support('google.com', [ 497 'check_aaaa' => true, 498 'check_connectivity' => true, 499 'check_dns' => true, 500 'check_latency' => true 501 ]); 502 echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; 503 504 // 批量检测 505 echo "\n批量检测:\n"; 506 $batchResults = $ipv6Tool->batchCheck(['google.com', 'github.com', 'facebook.com'], [ 507 'check_aaaa' => true, 508 'check_connectivity' => false 509 ]); 510 echo json_encode($batchResults, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; 511 512 } catch (Exception $e) { 513 echo "检测失败: " . $e->getMessage() . "\n"; 514 } 515} 516 517// 如果直接运行此文件,执行示例 518if (basename(__FILE__) === basename($_SERVER['SCRIPT_NAME'] ?? '')) { 519 example(); 520} 521?>
-
ipv6_check (PY)
1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3""" 4IPv6检测工具 - Python实现 5检测网站是否支持IPv6访问 6""" 7 8import socket 9import time 10import requests 11import json 12from typing import Dict, List, Optional, Any 13from dataclasses import dataclass 14from concurrent.futures import ThreadPoolExecutor, as_completed 15 16 17@dataclass 18class TestResult: 19 """测试结果数据类""" 20 test: str 21 status: str # 'success', 'warning', 'error' 22 status_text: str 23 details: str 24 ipv6_addresses: List[str] = None 25 additional_data: Dict[str, Any] = None 26 27 28class IPv6CheckTool: 29 """IPv6检测工具类""" 30 31 def __init__(self): 32 self.default_nameservers = [ 33 '2001:4860:4860::8888', # Google DNS IPv6 34 '2001:4860:4860::8844', # Google DNS IPv6备用 35 '2606:4700:4700::1111', # Cloudflare DNS IPv6 36 '2606:4700:4700::1001' # Cloudflare DNS IPv6备用 37 ] 38 self.timeout = 10 39 self.session = requests.Session() 40 self.session.timeout = self.timeout 41 42 def check_ipv6_support(self, domain: str, options: Dict[str, bool] = None) -> Dict[str, Any]: 43 """ 44 检测域名的IPv6支持情况 45 46 Args: 47 domain: 域名 48 options: 检测选项 49 50 Returns: 51 检测结果字典 52 """ 53 if options is None: 54 options = {} 55 56 check_aaaa = options.get('check_aaaa', True) 57 check_connectivity = options.get('check_connectivity', True) 58 check_dns = options.get('check_dns', True) 59 check_latency = options.get('check_latency', True) 60 61 results = { 62 'domain': domain, 63 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'), 64 'tests': [] 65 } 66 67 try: 68 # 检测AAAA记录 69 if check_aaaa: 70 aaaa_result = self.check_aaaa_record(domain) 71 results['tests'].append(aaaa_result) 72 73 # 检测IPv6连通性 74 if check_connectivity: 75 connectivity_result = self.check_ipv6_connectivity(domain) 76 results['tests'].append(connectivity_result) 77 78 # 检测DNS解析 79 if check_dns: 80 dns_result = self.check_dns_resolution(domain) 81 results['tests'].append(dns_result) 82 83 # 检测网络延迟 84 if check_latency: 85 latency_result = self.check_latency(domain) 86 results['tests'].append(latency_result) 87 88 # 生成总结 89 results['summary'] = self.generate_summary(results['tests']) 90 91 except Exception as error: 92 print(f'IPv6检测失败: {error}') 93 raise error 94 95 return results 96 97 def check_aaaa_record(self, domain: str) -> TestResult: 98 """ 99 检测AAAA记录 100 101 Args: 102 domain: 域名 103 104 Returns: 105 检测结果 106 """ 107 try: 108 # 使用socket查询AAAA记录 109 ipv6_addresses = [] 110 111 try: 112 # 尝试解析IPv6地址 113 info = socket.getaddrinfo(domain, 80, socket.AF_INET6) 114 for item in info: 115 if item[0] == socket.AF_INET6: 116 ipv6_addresses.append(item[4][0]) 117 except socket.gaierror: 118 pass 119 120 if ipv6_addresses: 121 return TestResult( 122 test='AAAA记录检测', 123 status='success', 124 status_text='支持', 125 details=f'找到 {len(ipv6_addresses)} 个IPv6地址记录', 126 ipv6_addresses=ipv6_addresses 127 ) 128 else: 129 return TestResult( 130 test='AAAA记录检测', 131 status='error', 132 status_text='不支持', 133 details='域名未配置IPv6地址记录', 134 ipv6_addresses=[] 135 ) 136 137 except Exception as error: 138 return TestResult( 139 test='AAAA记录检测', 140 status='error', 141 status_text='检测失败', 142 details=f'DNS查询失败: {str(error)}', 143 ipv6_addresses=[] 144 ) 145 146 def check_ipv6_connectivity(self, domain: str) -> TestResult: 147 """ 148 检测IPv6连通性 149 150 Args: 151 domain: 域名 152 153 Returns: 154 检测结果 155 """ 156 try: 157 # 首先获取IPv6地址 158 aaaa_result = self.check_aaaa_record(domain) 159 160 if aaaa_result.status == 'error': 161 return TestResult( 162 test='IPv6连通性检测', 163 status='error', 164 status_text='无法检测', 165 details='无法获取IPv6地址进行连通性检测', 166 ipv6_addresses=[] 167 ) 168 169 # 测试IPv6地址连通性 170 connectivity_results = [] 171 for ipv6_address in aaaa_result.ipv6_addresses: 172 try: 173 start_time = time.time() 174 # 尝试连接IPv6地址 175 sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) 176 sock.settimeout(5) 177 sock.connect((ipv6_address, 80)) 178 sock.close() 179 latency = (time.time() - start_time) * 1000 180 181 connectivity_results.append({ 182 'ipv6_address': ipv6_address, 183 'reachable': True, 184 'latency': latency 185 }) 186 except Exception as error: 187 connectivity_results.append({ 188 'ipv6_address': ipv6_address, 189 'reachable': False, 190 'latency': None, 191 'error': str(error) 192 }) 193 194 reachable_count = sum(1 for r in connectivity_results if r['reachable']) 195 total_count = len(connectivity_results) 196 197 if reachable_count == total_count: 198 return TestResult( 199 test='IPv6连通性检测', 200 status='success', 201 status_text='完全可达', 202 details=f'所有 {total_count} 个IPv6地址都可以访问', 203 ipv6_addresses=aaaa_result.ipv6_addresses, 204 additional_data={'connectivity_results': connectivity_results} 205 ) 206 elif reachable_count > 0: 207 return TestResult( 208 test='IPv6连通性检测', 209 status='warning', 210 status_text='部分可达', 211 details=f'{reachable_count}/{total_count} 个IPv6地址可以访问', 212 ipv6_addresses=aaaa_result.ipv6_addresses, 213 additional_data={'connectivity_results': connectivity_results} 214 ) 215 else: 216 return TestResult( 217 test='IPv6连通性检测', 218 status='error', 219 status_text='不可达', 220 details='所有IPv6地址都无法访问', 221 ipv6_addresses=aaaa_result.ipv6_addresses, 222 additional_data={'connectivity_results': connectivity_results} 223 ) 224 225 except Exception as error: 226 return TestResult( 227 test='IPv6连通性检测', 228 status='error', 229 status_text='检测失败', 230 details=f'连通性检测失败: {str(error)}', 231 ipv6_addresses=[] 232 ) 233 234 def check_dns_resolution(self, domain: str) -> TestResult: 235 """ 236 检测DNS解析 237 238 Args: 239 domain: 域名 240 241 Returns: 242 检测结果 243 """ 244 try: 245 # 检测IPv6 DNS解析 246 ipv6_addresses = [] 247 248 try: 249 # 尝试解析IPv6地址 250 info = socket.getaddrinfo(domain, 80, socket.AF_INET6) 251 for item in info: 252 if item[0] == socket.AF_INET6: 253 ipv6_addresses.append(item[4][0]) 254 except socket.gaierror: 255 pass 256 257 if ipv6_addresses: 258 return TestResult( 259 test='DNS解析检测', 260 status='success', 261 status_text='正常', 262 details='IPv6 DNS解析正常', 263 ipv6_addresses=ipv6_addresses 264 ) 265 else: 266 return TestResult( 267 test='DNS解析检测', 268 status='warning', 269 status_text='部分正常', 270 details='IPv6 DNS解析部分正常', 271 ipv6_addresses=[] 272 ) 273 274 except Exception as error: 275 return TestResult( 276 test='DNS解析检测', 277 status='error', 278 status_text='异常', 279 details=f'DNS解析异常: {str(error)}', 280 ipv6_addresses=[] 281 ) 282 283 def check_latency(self, domain: str) -> TestResult: 284 """ 285 检测网络延迟 286 287 Args: 288 domain: 域名 289 290 Returns: 291 检测结果 292 """ 293 try: 294 # 获取IPv6地址 295 aaaa_result = self.check_aaaa_record(domain) 296 297 if aaaa_result.status == 'error': 298 return TestResult( 299 test='网络延迟检测', 300 status='error', 301 status_text='无法检测', 302 details='无法获取IPv6地址进行延迟检测', 303 ipv6_addresses=[] 304 ) 305 306 # 测试延迟 307 latency_results = [] 308 for ipv6_address in aaaa_result.ipv6_addresses: 309 try: 310 start_time = time.time() 311 sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) 312 sock.settimeout(5) 313 sock.connect((ipv6_address, 80)) 314 sock.close() 315 latency = (time.time() - start_time) * 1000 316 317 latency_results.append({ 318 'ipv6_address': ipv6_address, 319 'latency': latency, 320 'status': 'excellent' if latency < 100 else 'good' if latency < 200 else 'poor' 321 }) 322 except Exception as error: 323 latency_results.append({ 324 'ipv6_address': ipv6_address, 325 'latency': None, 326 'status': 'failed', 327 'error': str(error) 328 }) 329 330 # 计算平均延迟 331 valid_latencies = [r['latency'] for r in latency_results if r['latency'] is not None] 332 if valid_latencies: 333 avg_latency = sum(valid_latencies) / len(valid_latencies) 334 status = 'success' if avg_latency < 100 else 'warning' if avg_latency < 200 else 'error' 335 status_text = '优秀' if avg_latency < 100 else '良好' if avg_latency < 200 else '较差' 336 details = f'平均延迟: {avg_latency:.1f}ms' 337 else: 338 status = 'error' 339 status_text = '检测失败' 340 details = '无法获取有效延迟数据' 341 avg_latency = None 342 343 return TestResult( 344 test='网络延迟检测', 345 status=status, 346 status_text=status_text, 347 details=details, 348 ipv6_addresses=aaaa_result.ipv6_addresses, 349 additional_data={ 350 'latency_results': latency_results, 351 'average_latency': avg_latency 352 } 353 ) 354 355 except Exception as error: 356 return TestResult( 357 test='网络延迟检测', 358 status='error', 359 status_text='检测失败', 360 details=f'延迟检测失败: {str(error)}', 361 ipv6_addresses=[] 362 ) 363 364 def generate_summary(self, tests: List[TestResult]) -> Dict[str, Any]: 365 """ 366 生成检测总结 367 368 Args: 369 tests: 检测结果列表 370 371 Returns: 372 总结信息 373 """ 374 success_count = sum(1 for t in tests if t.status == 'success') 375 warning_count = sum(1 for t in tests if t.status == 'warning') 376 error_count = sum(1 for t in tests if t.status == 'error') 377 total_count = len(tests) 378 379 if success_count == total_count: 380 status = 'success' 381 title = 'IPv6支持良好' 382 message = f'所有 {total_count} 个检测项目都通过,该网站完全支持IPv6访问。' 383 elif success_count > 0 or warning_count > 0: 384 status = 'warning' 385 title = 'IPv6部分支持' 386 message = f'{success_count} 个项目通过,{warning_count} 个项目警告,{error_count} 个项目失败。该网站对IPv6的支持有限。' 387 else: 388 status = 'error' 389 title = 'IPv6不支持' 390 message = f'所有 {total_count} 个检测项目都失败,该网站不支持IPv6访问。' 391 392 return { 393 'status': status, 394 'title': title, 395 'message': message, 396 'statistics': { 397 'total': total_count, 398 'success': success_count, 399 'warning': warning_count, 400 'error': error_count 401 } 402 } 403 404 def batch_check(self, domains: List[str], options: Dict[str, bool] = None) -> Dict[str, Any]: 405 """ 406 批量检测多个域名 407 408 Args: 409 domains: 域名列表 410 options: 检测选项 411 412 Returns: 413 批量检测结果 414 """ 415 results = {} 416 417 with ThreadPoolExecutor(max_workers=5) as executor: 418 future_to_domain = { 419 executor.submit(self.check_ipv6_support, domain, options): domain 420 for domain in domains 421 } 422 423 for future in as_completed(future_to_domain): 424 domain = future_to_domain[future] 425 try: 426 results[domain] = future.result() 427 except Exception as error: 428 results[domain] = { 429 'error': str(error), 430 'domain': domain, 431 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S') 432 } 433 434 return results 435 436 def is_valid_ipv6(self, ipv6: str) -> bool: 437 """ 438 验证IPv6地址格式 439 440 Args: 441 ipv6: IPv6地址 442 443 Returns: 444 是否为有效IPv6地址 445 """ 446 try: 447 socket.inet_pton(socket.AF_INET6, ipv6) 448 return True 449 except socket.error: 450 return False 451 452 453def example(): 454 """使用示例""" 455 ipv6_tool = IPv6CheckTool() 456 457 try: 458 # 单个域名检测 459 print('检测单个域名:') 460 result = ipv6_tool.check_ipv6_support('google.com', { 461 'check_aaaa': True, 462 'check_connectivity': True, 463 'check_dns': True, 464 'check_latency': True 465 }) 466 print(json.dumps(result, indent=2, ensure_ascii=False)) 467 468 # 批量检测 469 print('\n批量检测:') 470 batch_results = ipv6_tool.batch_check(['google.com', 'github.com', 'facebook.com'], { 471 'check_aaaa': True, 472 'check_connectivity': False 473 }) 474 print(json.dumps(batch_results, indent=2, ensure_ascii=False)) 475 476 except Exception as error: 477 print(f'检测失败: {error}') 478 479 480if __name__ == '__main__': 481 example()