作者 刘锟

update

@@ -16,6 +16,7 @@ use App\Models\Project\CountryCustom; @@ -16,6 +16,7 @@ use App\Models\Project\CountryCustom;
16 use App\Models\Project\Project; 16 use App\Models\Project\Project;
17 use Illuminate\Console\Command; 17 use Illuminate\Console\Command;
18 use App\Models\Domain\DomainInfo as DomainInfoModel; 18 use App\Models\Domain\DomainInfo as DomainInfoModel;
  19 +use Illuminate\Support\Facades\Log;
19 use Symfony\Component\Process\Process; 20 use Symfony\Component\Process\Process;
20 21
21 class DomainInfo extends Command 22 class DomainInfo extends Command
@@ -43,6 +44,9 @@ class DomainInfo extends Command @@ -43,6 +44,9 @@ class DomainInfo extends Command
43 */ 44 */
44 public function handle() 45 public function handle()
45 { 46 {
  47 + //先更新所有域名证书有效期
  48 + $this->startUpdateSslTime();
  49 +
46 //主站证书到期更新 50 //主站证书到期更新
47 $this->startUpdateCert(); 51 $this->startUpdateCert();
48 52
@@ -56,6 +60,47 @@ class DomainInfo extends Command @@ -56,6 +60,47 @@ class DomainInfo extends Command
56 } 60 }
57 61
58 /** 62 /**
  63 + * 更新域名证书有效期
  64 + * @author Akun
  65 + * @date 2024/09/06 11:16
  66 + */
  67 + public function startUpdateSslTime()
  68 + {
  69 + $domainModel = new DomainInfoModel();
  70 + $projectModel = new Project();
  71 + $serverIpModel = new ServersIp();
  72 + $list = $domainModel->where('status', '=', 1)->get();
  73 + foreach ($list as $v) {
  74 + $project_info = $projectModel->read(['id' => $v['project_id']], ['serve_id']);
  75 + if (!$project_info) {
  76 + continue;
  77 + }
  78 +
  79 + $servers_ip_info = $serverIpModel->read(['id' => $project_info['serve_id']], ['servers_id', 'ip', 'domain']);
  80 + if (!$servers_ip_info) {
  81 + continue;
  82 + }
  83 +
  84 + //除自建站项目外,记录已解析到别的ip的域名
  85 + if ($servers_ip_info['servers_id'] != ServerConfig::SELF_SITE_ID) {
  86 + //过滤已解析到别的ip的域名
  87 + if (!$this->check_cname($v['domain'], $servers_ip_info)) {
  88 + Log::channel('analyze_other')->error('域名 [' . $v['domain'] . '] 已解析到别的IP');
  89 + continue;
  90 + }
  91 + }
  92 +
  93 + //获取证书有效期并更新
  94 + $ssl_time = $this->getDomainSslTime($v['domain']);
  95 + if ($ssl_time['from'] && $ssl_time['to']) {
  96 + $v->certificate_start_time = $ssl_time['from'];
  97 + $v->certificate_end_time = $ssl_time['to'];
  98 + $v->save();
  99 + }
  100 + }
  101 + }
  102 +
  103 + /**
59 * 主站证书到期更新 104 * 主站证书到期更新
60 * @author Akun 105 * @author Akun
61 * @date 2024/02/26 10:26 106 * @date 2024/02/26 10:26
@@ -86,6 +131,7 @@ class DomainInfo extends Command @@ -86,6 +131,7 @@ class DomainInfo extends Command
86 131
87 //过滤已解析到别的ip的域名 132 //过滤已解析到别的ip的域名
88 if (!$this->check_cname($v['domain'], $servers_ip_info)) { 133 if (!$this->check_cname($v['domain'], $servers_ip_info)) {
  134 + Log::channel('analyze_other')->error('域名 [' . $v['domain'] . '] 已解析到别的IP');
89 continue; 135 continue;
90 } 136 }
91 137
@@ -143,6 +189,7 @@ class DomainInfo extends Command @@ -143,6 +189,7 @@ class DomainInfo extends Command
143 189
144 //过滤已解析到别的ip的域名 190 //过滤已解析到别的ip的域名
145 if (!$this->check_cname($amp_domain, $servers_ip_info)) { 191 if (!$this->check_cname($amp_domain, $servers_ip_info)) {
  192 + Log::channel('analyze_other')->error('域名 [' . $amp_domain . '] 已解析到别的IP');
146 continue; 193 continue;
147 } 194 }
148 195
@@ -190,6 +237,7 @@ class DomainInfo extends Command @@ -190,6 +237,7 @@ class DomainInfo extends Command
190 237
191 //过滤已解析到别的ip的域名 238 //过滤已解析到别的ip的域名
192 if (!$this->check_cname($v['custom_domain'], $servers_ip_info)) { 239 if (!$this->check_cname($v['custom_domain'], $servers_ip_info)) {
  240 + Log::channel('analyze_other')->error('域名 [' . $v['custom_domain'] . '] 已解析到别的IP');
193 continue; 241 continue;
194 } 242 }
195 243
@@ -207,6 +255,42 @@ class DomainInfo extends Command @@ -207,6 +255,42 @@ class DomainInfo extends Command
207 } 255 }
208 256
209 /** 257 /**
  258 + * 获取域名证书有效时间
  259 + * @param $domain
  260 + * @return string[]
  261 + * @author Akun
  262 + * @date 2024/08/29 9:59
  263 + */
  264 + public function getDomainSslTime($domain)
  265 + {
  266 + $valid_from = '';
  267 + $valid_to = '';
  268 + try {
  269 + $context = stream_context_create([
  270 + 'ssl' => [
  271 + 'capture_peer_cert' => true,
  272 + 'capture_peer_cert_chain' => false,
  273 + 'verify_peer' => false,
  274 + 'verify_peer_name' => false
  275 + ],
  276 + ]);
  277 + $stream = stream_socket_client('ssl://' . $domain . ':443', $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
  278 + if ($stream) {
  279 + $remote_cert = stream_context_get_params($stream)['options']['ssl']['peer_certificate'];
  280 + if ($remote_cert) {
  281 + $valid_from = date('Y-m-d H:i:s', openssl_x509_parse($remote_cert)['validFrom_time_t']);
  282 + $valid_to = date('Y-m-d H:i:s', openssl_x509_parse($remote_cert)['validTo_time_t']);
  283 + }
  284 + }
  285 + fclose($stream);
  286 + } catch (\Exception $e) {
  287 + $valid_from = '';
  288 + $valid_to = '';
  289 + }
  290 + return ['from' => $valid_from, 'to' => $valid_to];
  291 + }
  292 +
  293 + /**
210 * 验证是否cname或者A记录解析到目标服务器 294 * 验证是否cname或者A记录解析到目标服务器
211 * @param $domain 295 * @param $domain
212 * @param $server_info 296 * @param $server_info
@@ -101,6 +101,12 @@ return [ @@ -101,6 +101,12 @@ return [
101 'via' => \App\Factory\LogFormatterFactory::class, 101 'via' => \App\Factory\LogFormatterFactory::class,
102 'prefix' => 'wechatside', 102 'prefix' => 'wechatside',
103 ], 103 ],
  104 + //
  105 + 'analyze_other' => [
  106 + 'driver' => 'custom',
  107 + 'via' => \App\Factory\LogFormatterFactory::class,
  108 + 'prefix' => 'analyze_other',
  109 + ],
104 'stack' => [ 110 'stack' => [
105 'driver' => 'stack', 111 'driver' => 'stack',
106 'channels' => ['single'], 112 'channels' => ['single'],