feat: add connection tarpit for malicious bot traffic

Implements slow-drip response handler for known bot paths (wp-admin, phpmyadmin, etc.) to waste attacker resources. Includes per-IP and global connection limits, configurable delays, and random chunking. Also applies clippy lint fixes across codebase.
This commit is contained in:
2026-01-05 18:19:09 -06:00
parent 553bae5a7f
commit 2a710d584e
12 changed files with 799 additions and 137 deletions
+46 -42
View File
@@ -1,52 +1,56 @@
<script lang="ts">
import type { OGImageSpec } from '$lib/og-types';
import type { OGImageSpec } from "$lib/og-types";
type Props = {
title: string;
subtitle?: string;
type: OGImageSpec['type'];
};
type Props = {
title: string;
subtitle?: string;
type: OGImageSpec["type"];
};
let { title, subtitle, type }: Props = $props();
let { title, subtitle, type }: Props = $props();
// Calculate font size based on title length (matching original logic)
const fontSize = $derived(title.length > 40 ? '60px' : '72px');
// Calculate font size based on title length (matching original logic)
const fontSize = $derived(title.length > 40 ? "60px" : "72px");
</script>
<div
style="display: flex; width: 1200px; height: 630px; background-color: #000000; color: #fafafa; font-family: 'Schibsted Grotesk', sans-serif; padding: 60px 80px;"
style="display: flex; width: 1200px; height: 630px; background-color: #000000; color: #fafafa; font-family: 'Schibsted Grotesk', sans-serif; padding: 60px 80px;"
>
<div
style="display: flex; flex-direction: column; justify-content: space-between; width: 100%; height: 100%;"
>
<!-- Content section -->
<div style="display: flex; flex-direction: column; flex: 1; justify-content: center;">
<h1
style="font-family: 'Hanken Grotesk', sans-serif; font-weight: 900; font-size: {fontSize}; line-height: 1.1; margin: 0; color: #ffffff;"
>
{title}
</h1>
{#if subtitle}
<p
style="font-family: 'Schibsted Grotesk', sans-serif; font-size: 36px; margin: 32px 0 0 0; color: #a1a1aa; line-height: 1.4;"
>
{subtitle}
</p>
{/if}
</div>
<div
style="display: flex; flex-direction: column; justify-content: space-between; width: 100%; height: 100%;"
>
<!-- Content section -->
<div
style="display: flex; flex-direction: column; flex: 1; justify-content: center;"
>
<h1
style="font-family: 'Hanken Grotesk', sans-serif; font-weight: 900; font-size: {fontSize}; line-height: 1.1; margin: 0; color: #ffffff;"
>
{title}
</h1>
{#if subtitle}
<p
style="font-family: 'Schibsted Grotesk', sans-serif; font-size: 36px; margin: 32px 0 0 0; color: #a1a1aa; line-height: 1.4;"
>
{subtitle}
</p>
{/if}
</div>
<!-- Footer -->
<div
style="display: flex; justify-content: space-between; align-items: flex-end; border-top: 2px solid #27272a; padding-top: 24px;"
>
<div style="font-size: 28px; color: #71717a; font-weight: 500;">xevion.dev</div>
{#if type === 'project'}
<div
style="font-size: 24px; color: #52525b; text-transform: uppercase; letter-spacing: 0.05em;"
>
PROJECT
</div>
{/if}
</div>
</div>
<!-- Footer -->
<div
style="display: flex; justify-content: space-between; align-items: flex-end; border-top: 2px solid #27272a; padding-top: 24px;"
>
<div style="font-size: 28px; color: #71717a; font-weight: 500;">
xevion.dev
</div>
{#if type === "project"}
<div
style="font-size: 24px; color: #52525b; text-transform: uppercase; letter-spacing: 0.05em;"
>
PROJECT
</div>
{/if}
</div>
</div>
</div>
+5 -2
View File
@@ -15,7 +15,9 @@
class="max-w-2xl mx-4 border-b border-zinc-700 divide-y divide-zinc-700 sm:mx-6"
>
<div class="flex flex-col pb-4">
<span class="text-2xl font-bold text-white sm:text-3xl">Ryan Walters,</span>
<span class="text-2xl font-bold text-white sm:text-3xl"
>Ryan Walters,</span
>
<span class="text-xl font-normal text-zinc-400 sm:text-2xl">
Full-Stack Software Engineer
</span>
@@ -45,7 +47,8 @@
class="flex items-center gap-x-1.5 px-1.5 py-1 rounded-sm bg-zinc-900 shadow-sm hover:bg-zinc-800 transition-colors"
>
<IconSimpleIconsLinkedin class="size-4 text-zinc-300" />
<span class="whitespace-nowrap text-sm text-zinc-100">LinkedIn</span>
<span class="whitespace-nowrap text-sm text-zinc-100">LinkedIn</span
>
</a>
<button
type="button"