mirror of
https://github.com/LowderPlay/cheburcheck.git
synced 2026-03-21 11:05:02 +00:00
* add asn and cidr subnet support - parse AS numbers (AS13335 format) - fetch prefixes from ripe stat api - cache asn data for 24h, check results for 1h - sample ips across subnets for checking - show asn stats and prefix lists in ui - link asn in results for quick lookup - collapsible lists for long prefix/network lists - trim whitespace from search input * refactor: improve code structure and add enhanced error messages * refactor: replace match with if let for single branch pattern * fix: don't store ASN in database * chore: bump version --------- Co-authored-by: Lowder <me@lowderplay.dev>
315 lines
14 KiB
Text
315 lines
14 KiB
Text
{% extends 'base' %}
|
||
|
||
{% block content %}
|
||
{% include 'search-form' %}
|
||
|
||
{% set warning = whitelist and not domain %}
|
||
|
||
<div class="result-panel {% if warning %}whitelist-theme{% elif found %}blocked-theme{% else %}clean-theme{% endif %}">
|
||
<div class="result-header">
|
||
<div class="icon-box status-icon">
|
||
{% if whitelist %}
|
||
<i data-lucide="shield-alert" width="32" height="32"></i>
|
||
{% elif blocked %}
|
||
<i data-lucide="shield-x" width="32" height="32"></i>
|
||
{% else %}
|
||
<i data-lucide="shield-check" width="32" height="32"></i>
|
||
{% endif %}
|
||
</div>
|
||
{% if warning %}
|
||
<div>
|
||
<h2>Белый список</h2>
|
||
<p class="subheading text-sm">
|
||
Ресурс находится в белом списке
|
||
</p>
|
||
</div>
|
||
{% elif found %}
|
||
<div>
|
||
<h2>Заблокирован</h2>
|
||
<p class="subheading text-sm">Ресурс был найден в списках блокировок</p>
|
||
</div>
|
||
{% else %}
|
||
<div>
|
||
<h2>Доступен</h2>
|
||
<p class="subheading text-sm">Ограничений не обнаружено</p>
|
||
</div>
|
||
{% endif %}
|
||
|
||
</div>
|
||
|
||
<div class="target-info">
|
||
<div class="target-info-label">{{ target_type }}:</div>
|
||
<div class="target-value target-display">{{ target }}</div>
|
||
</div>
|
||
|
||
{% if asn_info %}
|
||
<div class="asn-summary">
|
||
<div class="asn-stat">
|
||
<span class="asn-stat-label">Всего подсетей:</span>
|
||
<span class="asn-stat-value">{{ asn_info.prefixes | length }}</span>
|
||
</div>
|
||
{% if asn_info.blocked_prefixes | length > 0 %}
|
||
<div class="asn-stat">
|
||
<span class="asn-stat-label">Заблокировано:</span>
|
||
<span class="asn-stat-value alert">{{ asn_info.blocked_prefixes | length }}</span>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
<div class="details-grid">
|
||
<div class="detail-section">
|
||
<h3 class="section-title">Сетевые данные</h3>
|
||
{% if not asn_info %}
|
||
<div class="detail-row">
|
||
<span class="row-label">IP-адреса</span>
|
||
<div class="ip-list-container">
|
||
{% if ips | length == 1 %}
|
||
<span class="ip-item">{{ ips | first }}</span>
|
||
{% if subnet_size %}
|
||
<span class="ip-count">({{ subnet_size }} всего)</span>
|
||
{% endif %}
|
||
{% elif ips | length <= 5 %}
|
||
{% for ip in ips %}
|
||
<span class="ip-item">{{ ip }}</span>
|
||
{% endfor %}
|
||
{% if subnet_size %}
|
||
<span class="ip-count">({{ subnet_size }} всего)</span>
|
||
{% endif %}
|
||
{% else %}
|
||
<div class="ip-summary">
|
||
<span class="ip-range">{{ ips | first }} — {{ ips | last }}</span>
|
||
{% if subnet_size %}
|
||
<span class="ip-count">({{ subnet_size }} всего, проверено {{ ips | length }})</span>
|
||
{% else %}
|
||
<span class="ip-count">({{ ips | length }} адресов)</span>
|
||
{% endif %}
|
||
</div>
|
||
<details class="ip-list-details">
|
||
<summary class="ip-list-toggle">
|
||
Показать все
|
||
</summary>
|
||
<div class="ip-list-expanded">
|
||
{% for ip in ips %}
|
||
<span class="ip-item">{{ ip }}</span>
|
||
{% endfor %}
|
||
</div>
|
||
</details>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
<div class="detail-row">
|
||
<span class="row-label">Хостинг / ISP</span>
|
||
<span class="row-value">{% if geo.organisation %}{{ geo.organisation }}{% else %}-{% endif %}</span>
|
||
</div>
|
||
<div class="detail-row">
|
||
<span class="row-label">Локация</span>
|
||
<span class="row-value">{{ geo.location }}</span>
|
||
</div>
|
||
<div class="detail-row">
|
||
<span class="row-label">ASN</span>
|
||
<span class="row-value">
|
||
{% if geo.asn %}
|
||
<a href="/check?target={{ geo.asn }}" class="asn-link">{{ geo.asn }}</a>
|
||
{% else %}
|
||
-
|
||
{% endif %}
|
||
</span>
|
||
</div>
|
||
|
||
{% if asn_info %}
|
||
<div class="detail-row">
|
||
<span class="row-label">Подсети ASN</span>
|
||
<div class="prefix-list-container">
|
||
{% set ipv4_list = [] %}
|
||
{% set ipv6_list = [] %}
|
||
{% for prefix in asn_info.prefixes %}
|
||
{% if ":" in prefix %}
|
||
{% set_global ipv6_list = ipv6_list | concat(with=prefix) %}
|
||
{% else %}
|
||
{% set_global ipv4_list = ipv4_list | concat(with=prefix) %}
|
||
{% endif %}
|
||
{% endfor %}
|
||
|
||
{% set all_prefixes = ipv4_list | concat(with=ipv6_list) %}
|
||
{% if all_prefixes | length <= 10 %}
|
||
<div>
|
||
{% for prefix in all_prefixes %}
|
||
<p class="row-value">{{ prefix }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
{% else %}
|
||
<div>
|
||
{% for prefix in all_prefixes | slice(end=10) %}
|
||
<p class="row-value">{{ prefix }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
<details class="prefix-list-details">
|
||
<summary class="prefix-list-toggle">
|
||
Показать все ({{ all_prefixes | length }})
|
||
</summary>
|
||
<div class="prefix-list-expanded">
|
||
{% for prefix in all_prefixes %}
|
||
<p class="row-value">{{ prefix }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
</details>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="detail-section">
|
||
<h3 class="reason-header">Нахождение в списках</h3>
|
||
<div class="detail-row">
|
||
<span class="row-label">CDN</span>
|
||
{% if providers %}
|
||
<p class="row-value alert">НАЙДЕН</p>
|
||
{% else %}
|
||
<span class="row-value">Не найден</span>
|
||
{% endif %}
|
||
</div>
|
||
{% if providers %}
|
||
{% for provider, networks in providers %}
|
||
<div class="detail-row">
|
||
<span class="row-label">{{ provider }}</span>
|
||
<div class="cdn-networks-container">
|
||
{% if networks | length <= 5 %}
|
||
{% for network in networks %}
|
||
<p class="row-value">{{ network.cidr }}</p>
|
||
{% endfor %}
|
||
{% else %}
|
||
<div>
|
||
{% for network in networks | slice(end=5) %}
|
||
<p class="row-value">{{ network.cidr }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
<details class="cdn-networks-details">
|
||
<summary class="cdn-networks-toggle">
|
||
Показать все ({{ networks | length }})
|
||
</summary>
|
||
<div class="cdn-networks-expanded">
|
||
{% for network in networks %}
|
||
<p class="row-value">{{ network.cidr }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
</details>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
{% endif %}
|
||
|
||
{% if whitelist %}
|
||
<div class="detail-row">
|
||
<a href="/kb/whitelist" class="row-label">Белый список (?)</a>
|
||
<span class="row-value success">
|
||
НАЙДЕН - <span class="hint"
|
||
title="Дата последнего сканирования, когда данный домен был найден в белом списке">
|
||
<script>
|
||
document.write(new Date("{{ whitelist.last_ok }}").toLocaleDateString());
|
||
</script>
|
||
</span>
|
||
</span>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<div class="detail-row">
|
||
<span class="row-label">Реестр РКН</span>
|
||
|
||
{% if domain %}
|
||
<span class="row-value alert">ОГРАНИЧЕН</span>
|
||
{% elif blocked_subnets %}
|
||
<span class="row-value alert hint"
|
||
title="Адреса пересекаются с подсетями заблокированных доменов (не гарантирует блокировку)">
|
||
IP-АДРЕСА
|
||
</span>
|
||
{% else %}
|
||
<span class="row-value">Не найден</span>
|
||
{% endif %}
|
||
</div>
|
||
|
||
{% if domain %}
|
||
<div class="detail-row">
|
||
<span class="row-label">Заблокированный домен</span>
|
||
<span class="row-value">{{ domain }}</span>
|
||
</div>
|
||
{% endif %}
|
||
{% if blocked_subnets and not asn_info %}
|
||
<div class="detail-row">
|
||
<span class="row-label">Заблокированные подсети</span>
|
||
<div>
|
||
{% for network in blocked_subnets %}
|
||
<p class="row-value">{{ network }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
{% if asn_info and asn_info.blocked_prefixes | length > 0 %}
|
||
<div class="detail-row">
|
||
<span class="row-label">Заблокированные подсети ASN</span>
|
||
<div class="blocked-prefix-list-container">
|
||
{% if asn_info.blocked_prefixes | length <= 10 %}
|
||
<div>
|
||
{% for prefix in asn_info.blocked_prefixes %}
|
||
<p class="row-value alert">{{ prefix }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
{% else %}
|
||
<div>
|
||
{% for prefix in asn_info.blocked_prefixes | slice(end=10) %}
|
||
<p class="row-value alert">{{ prefix }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
<details class="blocked-prefix-list-details">
|
||
<summary class="blocked-prefix-list-toggle">
|
||
Показать все ({{ asn_info.blocked_prefixes | length }})
|
||
</summary>
|
||
<div class="blocked-prefix-list-expanded">
|
||
{% for prefix in asn_info.blocked_prefixes %}
|
||
<p class="row-value alert">{{ prefix }}</p>
|
||
{% endfor %}
|
||
</div>
|
||
</details>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
<div class="user-feedback-section">
|
||
<p class="feedback-prompt">У вас работает этот ресурс?</p>
|
||
<div class="feedback-buttons">
|
||
<button class="feedback-btn feedback-works" onclick="sendFeedback(true)">
|
||
<i data-lucide="thumbs-up" width="16" height="16"></i>
|
||
Работает
|
||
</button>
|
||
<button class="feedback-btn feedback-not-works" onclick="sendFeedback(false)">
|
||
<i data-lucide="thumbs-down" width="16" height="16"></i>
|
||
Не работает
|
||
</button>
|
||
</div>
|
||
<div class="feedback-status hidden">
|
||
<i data-lucide="thumbs-up" width="16" height="16"></i>
|
||
<span>Спасибо за ваш отзыв!</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function sendFeedback(works) {
|
||
document.querySelector('.feedback-buttons').classList.add('hidden');
|
||
document.querySelector('.feedback-prompt').classList.add('hidden');
|
||
document.querySelector('.feedback-status').classList.remove('hidden');
|
||
|
||
fetch(`/feedback/{{ id }}/${works}`, {
|
||
method: 'POST',
|
||
});
|
||
}
|
||
</script>
|
||
|
||
|
||
{% endblock content %}
|