Files
2026-09-17 09:53:30 +08:00

668 lines
16 KiB
HTML
Raw Permalink 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.
<!doctype html>
<!-- 雷池 SafeLine · 自定义错误页 · 403 攻击检测与黑名单(单文件自包含,无外部依赖) -->
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="robots" content="noindex" />
<title>403 · 攻击检测与黑名单 — 雷池 SafeLine</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='7' fill='%23e3676d'/%3E%3Cpath d='M5.6 5.6l4.8 4.8M10.4 5.6l-4.8 4.8' stroke='%23e3dede' stroke-width='1.7' stroke-linecap='round'/%3E%3C/svg%3E" />
<style>
/* ===== 页面底衬 ===== */
html {
height: 100%;
}
body {
box-sizing: border-box;
margin: 0;
min-height: 100vh;
min-height: 100svh;
display: grid;
place-items: center;
padding: 3em 1.5em;
background-color: #C13B45;
background-image: radial-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1.6px);
background-size: 26px 26px;
}
/* ===== 错误卡片 ===== */
#errorPage {
width: 22.5em;
min-height: 15em;
--backColor: rgb(227, 222, 222);
--firstColor: rgb(227, 103, 109);
--textColor: rgb(70, 68, 68);
border-radius: 1em;
position: relative;
font-family: Calibri, "Trebuchet MS", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
z-index: 1;
color: var(--textColor);
transform: rotate(3deg) skewX(3deg);
transition: all 0.25s ease-in-out;
}
#errorPage:hover {
transform: rotate(0deg) skewX(0deg);
}
#errorPage:hover #errorPage_Page {
transform: rotate(0deg) skewX(0deg);
box-shadow: -0.5em 0em var(--textColor);
}
#errorPage_Page svg {
transition: all 0.25s ease-in-out;
transform: rotate(0deg) skewX(3deg);
margin-top: 0.5em;
}
#errorPage:hover #errorPage_Page svg {
transform: rotate(-10deg) skewX(0deg);
}
#errorPage:hover #errorPage_BarSite {
transform: rotate(0deg) skewX(0deg);
box-shadow: -0.5em 0em var(--textColor);
}
#errorPage_Bar {
width: 100%;
height: 2em;
padding-left: 1.5em;
position: relative;
z-index: 3;
}
#errorPage_BarSite {
background-color: var(--backColor);
width: 5.5em;
height: 100%;
border-top-left-radius: 1em;
border-top-right-radius: 1em;
display: flex;
align-items: center;
color: var(--textColor);
padding-left: 0.5em;
box-shadow: -0.5em 0.25em var(--textColor);
transition: all 0.25s ease-in-out;
position: relative;
z-index: 1;
}
.errorPage_BarIcon {
width: 1em;
height: 1em;
background-color: var(--firstColor);
display: flex;
justify-content: center;
align-items: center;
border-radius: 1em;
}
.errorPage_BarIcon p {
font-size: 0.625em;
font-weight: bold;
margin: 0;
}
#errorPage_BarSiteText {
font-size: 0.78125em;
font-weight: bold;
padding-left: 0.5em;
margin: 0;
}
#errorPage_Page {
width: 100%;
min-height: 13em;
background: linear-gradient(var(--backColor), rgb(205, 200, 200));
border-radius: 1em;
box-shadow: -0.5em 0.5em var(--textColor);
display: flex;
flex-direction: column;
align-items: center;
padding-top: 0.5em;
padding-bottom: 1.05em;
transition: all 0.25s ease-in-out;
position: relative;
z-index: 3;
}
#errorPage_PageSearch {
width: 21.5em;
height: 1.25em;
border-radius: 10em;
background-color: var(--firstColor);
display: flex;
align-items: center;
padding-left: 0.5em;
}
.errorPage_PageText {
text-align: center;
font-size: 0.875em;
margin: 0;
padding: 0 1.1em;
}
.errorPage_PageText:nth-child(3) {
font-weight: bold;
font-size: 1.09375em;
margin-top: 0.8em;
padding: 0 0.9em;
}
.errorPage_PageText:nth-child(4) {
margin-top: 0.42em;
}
/* ===== 拦截信息(WAF 注入 event_id 时自动显示) ===== */
#errorPage_PageMeta {
display: none;
width: 82%;
margin-top: 0.9em;
padding-top: 0.55em;
border-top: 1px dashed rgba(70, 68, 68, 0.28);
font-size: 0.6875em;
line-height: 1.6;
color: rgba(70, 68, 68, 0.72);
text-align: center;
word-break: break-all;
}
.errorPage_PageSearchB {
width: 0.75em;
height: 0.75em;
border-radius: 10em;
margin-right: 0.5em;
}
.errorPage_PageSearchB:nth-child(1) {
animation: Ball1 10s linear infinite;
}
.errorPage_PageSearchB:nth-child(2) {
animation: Ball2 10s linear infinite;
}
.errorPage_PageSearchB:nth-child(3) {
animation: Ball3 10s linear infinite;
}
.errorPage_PageSearchB:nth-child(4) {
animation: Ball4 10s linear infinite;
}
.errorPage_PageSearchB:nth-child(5) {
animation: Ball5 10s linear infinite;
}
.errorPage_PageSearchB:nth-child(6) {
animation: Ball6 10s linear infinite;
}
.errorPage_PageSearchB:nth-child(7) {
animation: Ball7 10s linear infinite;
}
.errorPage_PageSearchB:nth-child(8) {
animation: Ball8 10s linear infinite;
}
@keyframes Ball1 {
0% {
background-color: var(--backColor);
}
2.5% {
background-color: var(--textColor);
}
97.5% {
background-color: var(--textColor);
}
100% {
background-color: var(--backColor);
}
}
@keyframes Ball2 {
0% {
background-color: var(--firstColor);
}
2.5% {
background-color: var(--backColor);
}
5% {
background-color: var(--textColor);
}
7.5% {
background-color: var(--textColor);
}
95% {
background-color: var(--textColor);
}
100% {
background-color: var(--firstColor);
}
}
@keyframes Ball3 {
0% {
background-color: var(--firstColor);
}
2.5% {
background-color: var(--firstColor);
}
5% {
background-color: var(--backColor);
}
7.5% {
background-color: var(--textColor);
}
10% {
background-color: var(--textColor);
}
92.5% {
background-color: var(--textColor);
}
95% {
background-color: var(--firstColor);
}
100% {
background-color: var(--firstColor);
}
}
@keyframes Ball4 {
0% {
background-color: var(--firstColor);
}
5% {
background-color: var(--firstColor);
}
7.5% {
background-color: var(--backColor);
}
10% {
background-color: var(--textColor);
}
12.5% {
background-color: var(--textColor);
}
60% {
background-color: var(--textColor);
}
62.5% {
background-color: var(--firstColor);
}
65% {
background-color: var(--backColor);
}
67.5% {
background-color: var(--textColor);
}
90% {
background-color: var(--textColor);
}
92.5% {
background-color: var(--firstColor);
}
100% {
background-color: var(--firstColor);
}
}
@keyframes Ball5 {
0% {
background-color: var(--firstColor);
}
7.5% {
background-color: var(--firstColor);
}
10% {
background-color: var(--backColor);
}
12.5% {
background-color: var(--textColor);
}
15% {
background-color: var(--textColor);
}
57.5% {
background-color: var(--textColor);
}
60% {
background-color: var(--firstColor);
}
65% {
background-color: var(--firstColor);
}
67.5% {
background-color: var(--backColor);
}
70% {
background-color: var(--textColor);
}
87.5% {
background-color: var(--textColor);
}
90% {
background-color: var(--firstColor);
}
100% {
background-color: var(--firstColor);
}
}
@keyframes Ball6 {
0% {
background-color: var(--firstColor);
}
10% {
background-color: var(--firstColor);
}
12.5% {
background-color: var(--backColor);
}
15% {
background-color: var(--textColor);
}
17.5% {
background-color: var(--firstColor);
}
20% {
background-color: var(--backColor);
}
22.5% {
background-color: var(--textColor);
}
55% {
background-color: var(--textColor);
}
57.5% {
background-color: var(--firstColor);
}
67.5% {
background-color: var(--firstColor);
}
70% {
background-color: var(--backColor);
}
72.5% {
background-color: var(--textColor);
}
85% {
background-color: var(--textColor);
}
87.5% {
background-color: var(--firstColor);
}
100% {
background-color: var(--firstColor);
}
}
@keyframes Ball7 {
0% {
background-color: var(--firstColor);
}
20% {
background-color: var(--firstColor);
}
22.5% {
background-color: var(--backColor);
}
25% {
background-color: var(--textColor);
}
27.5% {
background-color: var(--firstColor);
}
30% {
background-color: var(--backColor);
}
32.5% {
background-color: var(--textColor);
}
52.5% {
background-color: var(--textColor);
}
55% {
background-color: var(--firstColor);
}
70% {
background-color: var(--firstColor);
}
72.5% {
background-color: var(--backColor);
}
75% {
background-color: var(--textColor);
}
77.5% {
background-color: var(--firstColor);
}
80% {
background-color: var(--backColor);
}
82.5% {
background-color: var(--textColor);
}
85% {
background-color: var(--firstColor);
}
100% {
background-color: var(--firstColor);
}
}
@keyframes Ball8 {
0% {
background-color: var(--firstColor);
}
30% {
background-color: var(--firstColor);
}
32.5% {
background-color: var(--backColor);
}
35% {
background-color: var(--textColor);
}
40% {
background-color: var(--textColor);
}
42.5% {
background-color: var(--firstColor);
}
45% {
background-color: var(--backColor);
}
47.5% {
background-color: var(--textColor);
}
50% {
background-color: var(--textColor);
}
52.5% {
background-color: var(--firstColor);
}
100% {
background-color: var(--firstColor);
}
}
/* ===== 响应式 ===== */
@media (max-width: 430px) {
body {
padding: 2em 1em;
}
#errorPage {
font-size: 14px;
}
}
@media (max-width: 350px) {
body {
padding: 1.5em 0.6em;
}
#errorPage {
font-size: 12px;
}
}
/* ===== 降低动态效果 ===== */
@media (prefers-reduced-motion: reduce) {
#errorPage,
#errorPage_Page,
#errorPage_BarSite,
#errorPage_Page svg {
transition: none;
}
#errorPage:hover {
transform: rotate(3deg) skewX(3deg);
}
#errorPage:hover #errorPage_Page {
transform: none;
box-shadow: -0.5em 0.5em var(--textColor);
}
#errorPage:hover #errorPage_BarSite {
transform: none;
box-shadow: -0.5em 0.25em var(--textColor);
}
#errorPage:hover #errorPage_Page svg {
transform: rotate(0deg) skewX(3deg);
}
}
</style>
</head>
<body>
<div id="errorPage">
<div id="errorPage_Bar">
<div id="errorPage_BarSite">
<div class="errorPage_BarIcon"><p>X</p></div>
<p id="errorPage_BarSiteText">Error 403</p>
</div>
</div>
<div id="errorPage_Page">
<div id="errorPage_PageSearch">
<div class="errorPage_PageSearchB"></div>
<div class="errorPage_PageSearchB"></div>
<div class="errorPage_PageSearchB"></div>
<div class="errorPage_PageSearchB"></div>
<div class="errorPage_PageSearchB"></div>
<div class="errorPage_PageSearchB"></div>
<div class="errorPage_PageSearchB"></div>
<div class="errorPage_PageSearchB"></div>
</div>
<svg
width="100px"
height="110px"
viewBox="0 0 200 220"
class="icon"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path
d="M100 26 L172 52 L172 104 C172 152 142 184 100 198 C58 184 28 152 28 104 L28 52 Z"
fill="#e3dede"
stroke="#464444"
stroke-width="6"
stroke-linejoin="round"
></path>
<circle cx="100" cy="104" r="40" fill="#e3676d" stroke="#464444" stroke-width="6"></circle>
<rect
x="73"
y="98"
width="54"
height="13"
rx="6.5"
fill="#e3dede"
stroke="#464444"
stroke-width="5"
transform="rotate(45 100 104)"
></rect>
<path
d="M0 -14 L3.5 -3.5 L14 0 L3.5 3.5 L0 14 L-3.5 3.5 L-14 0 L-3.5 -3.5 Z"
fill="#e3676d"
transform="translate(168 34) scale(0.95)"
></path>
<path
d="M0 -14 L3.5 -3.5 L14 0 L3.5 3.5 L0 14 L-3.5 3.5 L-14 0 L-3.5 -3.5 Z"
fill="#e3676d"
transform="translate(34 46) scale(0.5)"
></path>
<circle cx="36" cy="182" r="5" fill="#464444"></circle>
</svg>
<p class="errorPage_PageText">这道门为安全而关。请求已被安全系统拦截。</p>
<p class="errorPage_PageText">Some doors stay closed for good reason. This request was flagged by our security systems.</p>
<div id="errorPage_PageMeta">
<div id="errorPage_EventID"></div>
<div id="errorPage_TypeTime"></div>
</div>
</div>
</div>
<script>
(function () {
function findInjected() {
var i;
var list;
var n;
for (n = document.documentElement.nextSibling; n; n = n.nextSibling) {
if (n.nodeType === 8 && n.data.indexOf("event_id:") !== -1) return n.data;
}
list = document.body ? document.body.childNodes : [];
for (i = list.length - 1; i >= 0; i--) {
if (list[i].nodeType === 8 && list[i].data.indexOf("event_id:") !== -1) return list[i].data;
}
list = document.childNodes;
for (i = list.length - 1; i >= 0; i--) {
if (list[i].nodeType === 8 && list[i].data.indexOf("event_id:") !== -1) return list[i].data;
}
return "";
}
function two(n) {
return n < 10 ? "0" + n : "" + n;
}
function init() {
var raw = findInjected();
if (!raw) return;
var parts = raw.replace(/\s+/g, " ").trim().split(" ");
var get = function (key) {
var i = parts.indexOf(key + ":");
return i > -1 && parts[i + 1] ? parts[i + 1] : "";
};
var eventId = get("event_id");
var type = get("TYPE");
if (!eventId && !type) return;
var meta = document.getElementById("errorPage_PageMeta");
var elId = document.getElementById("errorPage_EventID");
var elType = document.getElementById("errorPage_TypeTime");
if (!meta || !elId || !elType) return;
var d = new Date();
var time = d.getFullYear() + "-" + two(d.getMonth() + 1) + "-" + two(d.getDate()) + " " + two(d.getHours()) + ":" + two(d.getMinutes());
elId.textContent = eventId ? "事件ID:" + eventId : "";
elType.textContent = (type ? "类型:" + type + " · " : "") + "拦截时间:" + time;
meta.style.display = "block";
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
window.addEventListener("load", init);
})();
</script>
</body>
</html>