Files
ProxyPanel/app/Components/IP.php
兔姬桑 0fc31ebd35 Fixed/优化 (中转)节点设置相关BUG
1. 修复设置端口属性后,为正确修改/添加的BUG;
2. 优化了检测线路地理时会出现的无法明确定位问题的异常报错;
3. 修复了多次一举的线路表单验证,导致多IP类型线路无法正常添加;
4. 优化中转线路的添加与修改;
5. 明确中转线路一切代理设置信息,继承母线路;
2022-06-22 00:57:53 +08:00

220 lines
7.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Components;
use Exception;
use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
use Http;
use IP2Location\Database;
use Ip2Region;
use ipip\db\City;
use Log;
use MaxMind\Db\Reader\InvalidDatabaseException;
class IP
{
// 获取IP地址信息
public static function getIPInfo($ip)
{
// IPv6 推荐使用ip.sb
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
Log::notice('识别到IPv6尝试解析'.$ip);
$ipInfo = self::IPSB($ip);
} else {
$ipInfo = self::ip2Region($ip);
if (! $ipInfo) {
Log::warning('无法识别尝试使用【IPIP库】库解析'.$ip);
$ipInfo = self::ip2Location($ip);
}
}
return $ipInfo;
}
// 通过api.ip.sb查询IP地址的详细信息
public static function IPSB($ip)
{
$response = Http::timeout(15)->get('https://api.ip.sb/geoip/'.$ip);
if ($response->ok()) {
return $response->json();
}
Log::warning('api.ip.sb解析'.$ip.'异常: '.$response->body());
return false;
}
// 通过ip2Region查询IP地址的详细信息 ← 聚合 淘宝IP库GeoIP纯真IP库
public static function ip2Region(string $ip)
{
$ipInfo = false;
try {
$ipInfo = (new Ip2Region())->memorySearch($ip);
} catch (Exception $e) {
Log::error('【淘宝IP库】错误信息'.$e->getMessage());
}
if ($ipInfo) {
$location = explode('|', $ipInfo['region']);
if ($location) {
return [
'country' => $location[0] ?: '',
'province' => $location[2] ?: '',
'city' => $location[3] ?: '',
'isp' => $location[4] ?: '',
'area' => $location[1] ?: '',
];
}
}
return $ipInfo;
}
// 通过ip2Location查询IP地址的详细信息
public static function ip2Location(string $ip)
{
$filePath = database_path('IP2LOCATION-LITE-DB3.IPV6.BIN');
try {
$location = (new Database($filePath, Database::FILE_IO))
->lookup($ip, [Database::CITY_NAME, Database::REGION_NAME, Database::COUNTRY_NAME]);
return [
'country' => $location['countryName'],
'province' => $location['regionName'],
'city' => $location['cityName'],
];
} catch (Exception $e) {
Log::error('【ip2Location】错误信息'.$e->getMessage());
}
return false;
}
// 通过IPIP查询IP地址的详细信息
public static function IPIP(string $ip): array
{
$filePath = database_path('ipip.ipdb');
$location = (new City($filePath))->findMap($ip, 'CN');
return [
'country' => $location['country_name'],
'province' => $location['region_name'],
'city' => $location['city_name'],
];
}
// 通过ip.taobao.com查询IP地址的详细信息
public static function TaoBao(string $ip)
{
// 依据 https://ip.taobao.com/instructions 开发
$response = Http::timeout(15)->get('https://ip.taobao.com/outGetIpInfo?ip='.$ip.'&accessKey=alibaba-inc');
if ($response->ok()) {
$message = $response->json();
if ($message['code'] === 0) {
return [
'country' => $message['data']['country'] === 'XX' ? '' : $message['data']['country'],
'province' => $message['data']['region'] === 'XX' ? '' : $message['data']['region'],
'city' => $message['data']['city'] === 'XX' ? '' : $message['data']['city'],
'isp' => $message['data']['isp'] === 'XX' ? '' : $message['data']['isp'],
];
}
Log::warning('【淘宝IP库】返回错误信息'.$ip.PHP_EOL.$message['msg']);
} else {
Log::error('【淘宝IP库】解析异常'.$ip);
}
return false;
}
// 通过api.map.baidu.com查询IP地址的详细信息
public static function Baidu(string $ip)
{
if (! config('services.baidu.app_ak')) {
Log::error('【百度IP库】AK信息缺失');
return false;
}
// 依据 http://lbsyun.baidu.com/index.php?title=webapi/ip-api 开发
$response = Http::timeout(15)->get('https://api.map.baidu.com/location/ip?ak='.config('services.baidu.app_ak').'&'.$ip.'&coor=bd09ll');
if ($response->ok()) {
$message = $response->json();
if ($message['status'] === 0) {
return [
'country' => $message['content']['address_detail']['country'],
'province' => $message['content']['address_detail']['province'],
'city' => $message['content']['address_detail']['city'],
'area' => $message['address'],
];
}
Log::warning('【百度IP库】返回错误信息'.$ip.PHP_EOL.var_export($message['message'], true));
} else {
Log::error('【百度IP库】解析异常'.$ip);
}
return false;
}
// 通过GeoIP2查询IP地址的详细信息
public static function GeoIP2(string $ip)
{
$filePath = database_path('maxmind.mmdb');
try {
$location = (new Reader($filePath))->city($ip);
return [
'country' => $location->country->names['zh-CN'],
'province' => '',
'city' => $location->city->name ?? '',
];
} catch (AddressNotFoundException $e) {
Log::error('【GeoIP2】查询失败'.$ip);
} catch (InvalidDatabaseException $e) {
Log::error('【GeoIP2】数据库无效'.$ip);
}
return false;
}
// 获取访客真实IP
public static function getClientIP()
{
/*
* 访问时用localhost访问的读出来的是“::1”是正常情况
* ::1说明开启了IPv6支持这是IPv6下的本地回环地址的表示
* 使用IPv4地址访问或者关闭IPv6支持都可以不显示这个
*/
if (isset($_SERVER)) {
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
$ip = $_SERVER['REMOTE_ADDR'];
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
} else {
$ip = 'unknown';
}
} elseif (getenv('HTTP_X_FORWARDED_FOR')) {
$ip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('HTTP_CLIENT_IP')) {
$ip = getenv('HTTP_CLIENT_IP');
} else {
$ip = getenv('REMOTE_ADDR');
}
if (trim($ip) === '::1') {
$ip = '127.0.0.1';
}
return $ip;
}
}