NetworkDetection.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. namespace App\Components;
  3. use Http;
  4. use Log;
  5. class NetworkDetection
  6. {
  7. /**
  8. * 用外部API进行Ping检测.
  9. *
  10. * @param string $ip 被检测的IP或者域名
  11. *
  12. * @return bool|array
  13. */
  14. public static function ping(string $ip)
  15. {
  16. $url = 'https://api.oioweb.cn/api/hostping.php?host='.$ip; // https://api.iiwl.cc/api/ping.php?host=
  17. $response = Http::timeout(15)->retry(2)->get($url);
  18. // 发送成功
  19. if ($response->ok()) {
  20. $message = $response->json();
  21. if ($message && $message['code']) {
  22. return $message['data'];
  23. }
  24. // 发送失败
  25. Log::warning('【PING】检测'.$ip.'时,返回'.var_export($message, true));
  26. return false;
  27. }
  28. Log::warning('【PING】检测'.$ip.'时,接口返回异常访问链接:'.$url);
  29. // 发送错误
  30. return false;
  31. }
  32. /**
  33. * 通过众多API进行节点阻断检测.
  34. *
  35. * @param string $ip 被检测的IP
  36. * @param bool $is_icmp TRUE 为ICMP,FALSE 为tcp
  37. * @param int|null $port 检测端口,默认为空
  38. *
  39. * @return bool|string
  40. */
  41. public function networkCheck(string $ip, bool $is_icmp, int $port = null)
  42. {
  43. $round = 0;
  44. // 依次尝试接口
  45. while (true) {
  46. switch ($round) {
  47. case 0:
  48. $ret = $this->idcWiki($ip, $is_icmp, $port);
  49. break;
  50. case 1:
  51. $ret = $this->flyzy2005($ip, $is_icmp, $port);
  52. break;
  53. case 2:
  54. $ret = $this->vps234($ip, $is_icmp);
  55. break;
  56. case 3:
  57. $ret = $this->vpsaff($ip, $is_icmp, $port);
  58. break;
  59. default:
  60. return false;
  61. }
  62. if ($ret !== false) {
  63. return $ret;
  64. }
  65. $round++;
  66. }
  67. }
  68. private function idcWiki(string $ip, bool $is_icmp, int $port = null)
  69. {
  70. if ($is_icmp) {
  71. $type_string = 'icmp/';
  72. $checkName = 'ICMP';
  73. } else {
  74. $type_string = 'tcp_ack/';
  75. $checkName = 'TCP';
  76. }
  77. if ($port) {
  78. $port = '/'.$port;
  79. $type_string = 'tcp_port/';
  80. }
  81. $url = "https://api.50network.com/china-firewall/check/ip/{$type_string}{$ip}{$port}";
  82. $response = Http::timeout(15)->get($url);
  83. if ($response->ok()) {
  84. $message = $response->json();
  85. if (! $message) {
  86. Log::warning('【'.$checkName.'阻断检测】检测'.$ip.'时,接口返回异常访问链接:'.$url);
  87. return false;
  88. }
  89. if (! $message['success']) {
  90. if ($message['error'] && $message['error'] === 'execute timeout (3s)') {
  91. return false;
  92. }
  93. Log::warning('【'.$checkName.'阻断检测】检测'.$ip.$port.'时,返回'.var_export($message, true));
  94. return false;
  95. }
  96. if ($message['firewall-enable'] && $message['firewall-disable']) {
  97. return '通讯正常'; // 正常
  98. }
  99. if ($message['firewall-enable'] && ! $message['firewall-disable']) {
  100. return '海外阻断'; // 国外访问异常
  101. }
  102. if (! $message['firewall-enable'] && $message['firewall-disable']) {
  103. return '国内阻断'; // 被墙
  104. }
  105. return '机器宕机'; // 服务器宕机
  106. }
  107. return false;
  108. }
  109. private function flyzy2005(string $ip, bool $is_icmp, int $port = null)
  110. {
  111. $cn = "https://mini.flyzy2005.cn/ip_check.php?ip={$ip}&port={$port}";
  112. $us = "https://mini.flyzy2005.cn/ip_check_outside.php?ip={$ip}&port={$port}";
  113. $checkName = $is_icmp ? 'icmp' : 'tcp';
  114. $response_cn = Http::timeout(15)->get($cn);
  115. $response_us = Http::timeout(15)->get($us);
  116. if ($response_cn->ok() && $response_us->ok()) {
  117. $cn = $response_cn->json();
  118. $us = $response_us->json();
  119. if (! $cn || ! $us) {
  120. Log::warning("【{$checkName}阻断检测】检测{$ip}时,接口返回异常访问链接:{$cn} | {$us}");
  121. return false;
  122. }
  123. if ($cn[$checkName] === 'success' && $us['outside_'.$checkName] === 'success') {
  124. return '通讯正常'; // 正常
  125. }
  126. if ($cn[$checkName] === 'success' && $us['outside_'.$checkName] !== 'success') {
  127. return '海外阻断'; // 国外访问异常
  128. }
  129. if ($cn[$checkName] !== 'success' && $us['outside_'.$checkName] === 'success') {
  130. return '国内阻断'; // 被墙
  131. }
  132. return '机器宕机'; // 服务器宕机
  133. }
  134. return false;
  135. }
  136. private function vps234(string $ip, bool $is_icmp)
  137. {
  138. $url = 'https://www.vps234.com/ipcheck/getdata/';
  139. $checkName = $is_icmp ? 'ICMP' : 'TCP';
  140. $response = Http::timeout(15)->withoutVerifying()->asForm()->post($url, ['ip' => $ip]);
  141. if ($response->ok()) {
  142. $message = $response->json();
  143. if (! $message) {
  144. Log::warning('【'.$checkName.'阻断检测】检测'.$ip.'时,接口返回异常访问链接:'.$url);
  145. return false;
  146. }
  147. if (! $message['data']['success']) {
  148. Log::warning('【'.$checkName.'阻断检测】检测'.$ip.'时,返回'.var_export($message, true));
  149. return false;
  150. }
  151. if ($message['data']['data']['inner'.$checkName] && $message['data']['data']['out'.$checkName]) {
  152. return '通讯正常'; // 正常
  153. }
  154. if ($message['data']['data']['inner'.$checkName] && ! $message['data']['data']['out'.$checkName]) {
  155. return '海外阻断'; // 国外访问异常
  156. }
  157. if (! $message['data']['data']['inner'.$checkName] && $message['data']['data']['out'.$checkName]) {
  158. return '国内阻断'; // 被墙
  159. }
  160. return '机器宕机'; // 服务器宕机
  161. }
  162. return false;
  163. }
  164. private function vpsaff(string $ip, bool $is_icmp, int $port = null)
  165. {
  166. $cn = "https://api.24kplus.com/ipcheck?host={$ip}&port={$port}";
  167. $us = "https://api.vpsaff.net/ipcheck?host={$ip}&port={$port}";
  168. $checkName = $is_icmp ? 'ping' : 'tcp';
  169. $response_cn = Http::timeout(15)->get($cn);
  170. $response_us = Http::timeout(15)->get($us);
  171. if ($response_cn->ok() && $response_us->ok()) {
  172. $cn = $response_cn->json();
  173. $us = $response_us->json();
  174. if (! $cn || ! $us) {
  175. Log::warning("【{$checkName}阻断检测】检测{$ip}时,接口返回异常访问链接:{$cn} | {$us}");
  176. return false;
  177. }
  178. if (! $cn['code'] || ! $us['code']) {
  179. Log::warning('【'.$checkName.'阻断检测】检测'.$ip.$port.'时,返回'.var_export($cn, true).var_export($us, true));
  180. return false;
  181. }
  182. if ($cn['data'][$checkName] && $us['data'][$checkName]) {
  183. return '通讯正常'; // 正常
  184. }
  185. if ($cn['data'][$checkName] && ! $us['data'][$checkName]) {
  186. return '海外阻断'; // 国外访问异常
  187. }
  188. if (! $cn['data'][$checkName] && $us['data'][$checkName]) {
  189. return '国内阻断'; // 被墙
  190. }
  191. return '机器宕机'; // 服务器宕机
  192. }
  193. return false;
  194. }
  195. }