Zugriff basierend auf dem IP-Standort sperren

Autorenname:Lisa Farrell · 2026-01-18

Eine Frontend-Zugriffskontrolllösung basierend auf dem IP-Standort: Beim Laden der Seite wird https://my.ipin.io/info abgefragt, um den Ländercode (country) des Besuchers zu erhalten. Wenn country als TW (oder andere von dir konfigurierte Regionen) erkannt wird, stellt die Seite keine normalen Inhalte mehr bereit, sondern beendet den Zugriffsablauf direkt im Frontend.

Viele Anforderungen wie „Zugriff nach Region einschränken“ dienen eigentlich nicht dazu, starke Sicherheit aufzubauen (im Sinne von Hackerabwehr), sondern sind typische Frontend-Szenarien:

  • Der Service ist in bestimmten Ländern/Regionen vorübergehend nicht verfügbar (z. B. aus Compliance-, Urheberrechts-, Zahlungs- oder Logistikgründen)
  • Direkt beim Betreten der Seite eine Regionsprüfung durchführen und dann entscheiden, ob Inhalte/Buttons/Download-Links angezeigt werden
  • Marketing-Aktionen gelten nur für bestimmte Regionen; andere Regionen benötigen direkt eine Meldung wie „außerhalb des Servicebereichs“ oder „nicht verfügbar“

Dieser Ansatz eignet sich besonders für das Frontend: Der Browser stellt direkt eine Anfrage GET https://my.ipin.io/info, und die API liefert Geodaten basierend auf der „IP, die die Anfrage auslöst“, zum Beispiel:

{"ip":"185.220.236.7","country":"TW","region":"Taiwan","city":"Taipei"}

Danach musst du nur `country === "TW"` prüfen, um die „Zugriff sperren“-Aktion auszuführen (zum Beispiel: eine „Zugriff verweigert“-Meldung anzeigen, 404-Text ausgeben oder die Originalseite mit deiner eigenen Fehlerseiten-Struktur überschreiben). Der entscheidende Punkt ist: Wir sprechen hier nicht über „Weiterleitungen“, sondern stellen das Ergebnis eindeutig als Fehler oder Zugriffverweigerung dar, sodass der Nutzer den finalen Zustand „nicht zugreifbar“ sieht.

1) Logik und Funktionsprinzip (2 Absätze)

Absatz 1: Ablauf
Der Nutzer öffnet die Webseite → der Browser fragt sofort https://my.ipin.io/info ab → erhält `country` → wenn es die Blacklist trifft (z. B. `TW`), wird die weitere Seitendarstellung sofort blockiert: Es werden keine normalen Inhalte mehr gerendert, sondern direkt ein Endzustand wie „Zugriff verweigert / 404 / benutzerdefinierter Fehler“ ausgegeben; andernfalls werden Funktionen und Inhalte normal weitergeladen.

Absatz 2: Warum das Frontend zu dieser API passt
Da der Browser eine Drittanbieter-API direkt aufruft, sieht der Drittanbieter die „öffentliche IP“ des Besuchers, und das zurückgegebene Land/die Region entspricht dem Nutzer selbst – genau der Effekt, den du willst.

2) Code-Implementierung (so einfach wie möglich, frontend-fokussiert)

2.1 Am einfachsten: bei Treffer „Zugriff verweigern“ (empfohlen)

Platziere das Snippet im <head> (je früher, desto besser). Bei Treffer überschreibt es den Seiteninhalt und zeigt eine klare „Zugriff verweigert“-Meldung. Du kannst den Text durch deinen eigenen Compliance- oder Verfügbarkeits-Hinweis ersetzen.

Beispiel A: Zugriff sperren, wenn country === "TW"

<script>
(async function () {
  try {
    const info = await fetch("https://my.ipin.io/info").then(r => r.json());
    if (info.country === "TW") {
      document.documentElement.innerHTML =
        "<head><title>403 Forbidden</title></head>" +
        "<body style='font-family:system-ui;padding:40px'>" +
        "<h1>403 Zugriff verweigert</h1>" +
        "<p>Der Dienst ist in deiner Region nicht verfügbar.</p>" +
        "</body>";
    }
  } catch (e) {
    // Wenn die Abfrage fehlschlägt, standardmäßig erlauben (kannst du auf „standardmäßig sperren“ ändern)
  }
})();
</script>

Beispiel B: Zugriff sperren, wenn NICHT TW (nur TW erlauben)

<script>
(async function () {
  try {
    const info = await fetch("https://my.ipin.io/info").then(r => r.json());
    if (info.country !== "TW") {
      document.documentElement.innerHTML =
        "<head><title>403 Forbidden</title></head>" +
        "<body style='font-family:system-ui;padding:40px'>" +
        "<h1>403 Zugriff verweigert</h1>" +
        "<p>Diese Seite ist nur in ausgewählten Regionen verfügbar.</p>" +
        "</body>";
    }
  } catch (e) {
    // Wenn die Abfrage fehlschlägt, standardmäßig erlauben (kannst du auf „standardmäßig sperren“ ändern)
  }
})();
</script>

Beispiel C: Zugriff sperren, wenn TW, US usw. (Sperrliste)

<script>
(async function () {
  const blocked = ["TW", "US"]; // Bei Treffer in der Liste sperren
  try {
    const info = await fetch("https://my.ipin.io/info").then(r => r.json());
    if (blocked.includes(info.country)) {
      document.documentElement.innerHTML =
        "<head><title>403 Forbidden</title></head>" +
        "<body style='font-family:system-ui;padding:40px'>" +
        "<h1>403 Zugriff verweigert</h1>" +
        "<p>Der Dienst ist in deiner Region nicht verfügbar.</p>" +
        "</body>";
    }
  } catch (e) {}
})();
</script>

2.2 404 Not Found ausgeben (Darstellung als „nicht verfügbar/nicht vorhanden“)

Manche Produkte möchten in bestimmten Regionen lieber so wirken, als „existiere die Seite nicht“, statt ausdrücklich „eingeschränkt“ zu melden. In diesem Fall kannst du den Seiteninhalt mit einer 404-Fehlerseiten-Struktur überschreiben. Hinweis: Das ist weiterhin eine Darstellung im Frontend und ändert nicht wirklich den HTTP-Statuscode, den der Server zurückgibt, ist aber für das Seitenerlebnis ausreichend eindeutig.

<script>
(async function () {
  try {
    const { country } = await fetch("https://my.ipin.io/info").then(r => r.json());
    if (country === "TW") {
      document.documentElement.innerHTML =
        "<head><title>404 Not Found</title></head>" +
        "<body style='font-family:system-ui;padding:40px'>" +
        "<h1>404 Not Found</h1>" +
        "<p>The requested URL was not found on this server.</p>" +
        "</body>";
    }
  } catch (e) {}
})();
</script>

2.3 Blacklist als Array (näher an realen Anforderungen)

In der Praxis sperrt man meist nicht nur eine Region, sondern pflegt eine Blacklist. Das folgende Beispiel bleibt minimal: Bei einem Treffer wird direkt „Zugriff verweigert“ ausgegeben.

<script>
(async function () {
  const blocked = ["TW"]; // Zu sperrende Länder-/Regionscodes
  try {
    const info = await fetch("https://my.ipin.io/info").then(r => r.json());
    if (blocked.includes(info.country)) {
      document.documentElement.innerHTML =
        "<head><title>403 Forbidden</title></head>" +
        "<body style='font-family:system-ui;padding:40px'>" +
        "<h1>403 Zugriff verweigert</h1>" +
        "<p>Der Dienst ist in deiner Region nicht verfügbar.</p>" +
        "</body>";
    }
  } catch (e) {}
})();
</script>

2.4 React (kürzeste nutzbare Variante: nach Treffer eine Fehlerseite anzeigen)

import { useEffect, useState } from "react";

export default function App() {
  const [blocked, setBlocked] = useState(false);

  useEffect(() => {
    (async () => {
      try {
        const info = await fetch("https://my.ipin.io/info").then(r => r.json());
        if (info.country === "TW") setBlocked(true);
      } catch (e) {}
    })();
  }, []);

  if (blocked) {
    return (
      <div style={{ fontFamily: "system-ui", padding: 40 }}>
        <h1>403 Zugriff verweigert</h1>
        <p>Der Dienst ist in deiner Region nicht verfügbar.</p>
      </div>
    );
  }

  return <div>...</div>;
}

2.5 Vue (ebenfalls kürzeste Variante: nach Treffer Fehlerinhalt anzeigen)

<script>
export default {
  data() {
    return { blocked: false };
  },
  async mounted() {
    try {
      const info = await fetch("https://my.ipin.io/info").then(r => r.json());
      if (info.country === "TW") this.blocked = true;
    } catch (e) {}
  }
}
</script>

<template>
  <div v-if="blocked" style="font-family:system-ui;padding:40px">
    <h1>403 Zugriff verweigert</h1>
    <p>Der Dienst ist in deiner Region nicht verfügbar.</p>
  </div>

  <div v-else>...</div>
</template>

3) Umsetzung in WordPress / Joomla / Magento / Shopify (Frontend-Ansatz + Code)

Die Idee ist überall gleich: ein „super-einfaches JS-Snippet“ in den globalen Head der Website (oder in die Layout-Datei) einfügen. Da dein Ziel „Frontend-Steuerung + Fehlerdarstellung“ ist, reicht es, wenn das Skript früh genug ausgeführt wird: Es kann die Regionsprüfung abschließen, bevor der Hauptinhalt rendert, und im Trefferfall direkt den Endzustand „Zugriff verweigert / 404 / Fehlermeldung“ anzeigen.

Ich empfehle, diese Variante überall zu verwenden (die einfachste „Zugriff verweigert“-Version):

<script>
(async function () {
  try {
    const info = await fetch("https://my.ipin.io/info").then(r => r.json());
    if (info.country === "TW") {
      document.documentElement.innerHTML =
        "<head><title>403 Forbidden</title></head>" +
        "<body style='font-family:system-ui;padding:40px'>" +
        "<h1>403 Zugriff verweigert</h1>" +
        "<p>Der Dienst ist in deiner Region nicht verfügbar.</p>" +
        "</body>";
    }
  } catch (e) {}
})();
</script>

3.1 WordPress

  • Option A (am einfachsten): ein Plugin zum Einfügen von Header/Footer-Skripten nutzen und das Skript im Header einfügen (websiteweit)
  • Option B: das Skript vor </head> in der Theme-Datei `header.php` einfügen

3.2 Joomla! / Joomla

  • Typischerweise im aktuellen Template in `index.php` den Bereich <head> finden und das Skript vor </head> einfügen
  • Oder eine Backend-/Template-Option nutzen, die das Einfügen von Custom Code/Custom HTML in den Head erlaubt (je nach Template unterschiedlich)

3.3 Magento (Frontend-Injection-Ansatz)

  • Wenn du nur eine Sperre auf Darstellungsebene möchtest, kannst du das Skript in den globalen Head des Themes einfügen (Head-Bereich im Theme/Layout)
  • Im Magento-Backend gibt es oft auch „HTML Head“ oder ähnliche Konfigurationen (je nach Version/Theme), deren Ziel es ist, Inhalte websiteweit in <head> einzufügen

> Da dein Ziel „so wenig Server-Code wie möglich“ ist, gehen wir hier nicht auf XML/Modul-Ansätze ein – wenn du das Skript in den Head einfügen kannst, funktioniert es.

3.4 Shopify

  • Online Store → Themes → Edit code
  • `theme.liquid` finden und das Skript vor </head> einfügen (websiteweit)

3.5 Andere gängige Systeme (allgemeines Muster)

  • Jedes System, das den globalen <head> bearbeiten kann: das Skript so früh wie möglich im Head platzieren
  • Wenn du nur bestimmte Seiten einschränken willst: das Skript nur in den entsprechenden Seiten-Templates hinzufügen

4) Zusammenfassung

Der Kern dieses Artikels lässt sich in einem Satz zusammenfassen:

> Der Browser fragt https://my.ipin.io/info ab und erhält { country }. Wenn country === "TW", wird der Seitenzugriff direkt durch die Darstellung „Zugriff verweigert / 404 / benutzerdefinierter Fehler“ beendet – damit ist eine Frontend-Lösung für das Sperren nach IP-Region umgesetzt.

Es ist kostengünstig und schnell umzusetzen und passt zu „Compliance-Hinweisen / Hinweisen zur regionalen Nichtverfügbarkeit / Frontend-Gating“. In vielen Fällen erfüllt eine „Fehlerdarstellung“ auf Frontend-Ebene bereits die Anforderungen von Produkt und Betrieb: Nutzer erkennen klar, dass die Seite in ihrer Region nicht verfügbar ist, und Hauptinhalte sowie Einstiegspunkte werden nicht weiter offengelegt. Wenn du strengere, „nicht umgehbare“ Kontrolle brauchst, kannst du zusätzlich eine Sperre auf Server- oder CDN-Ebene ergänzen.

5) Häufige Fragen (FAQ)

Q1: Kann Frontend-Blocking wirklich „Zugriff verweigern“?

Genauer gesagt ermöglicht es, dass die „Darstellungsebene“ dem Besucher ein klares Ablehnungsergebnis zeigt (z. B. 403/404/Fehlermeldungsseite) und normale Nutzer daran hindert, Seitenfunktionen weiter zu verwenden. Allerdings können technisch versierte Personen JavaScript deaktivieren oder Skripte verändern, daher ist es keine nicht umgehbare Sicherheitsmauer. Wenn du „absolutes Blocking“ brauchst, solltest du eine zusätzliche Sperrschicht auf Server- oder CDN-Ebene einbauen. Wenn es dir um Compliance- und Nichtverfügbarkeits-Hinweise geht, reicht Frontend-Blocking meist aus.

Q2: Warum das Skript in den <head> und so früh wie möglich?

Je früher geprüft wird, desto eher kann der Zugriff beendet werden, bevor der Hauptinhalt rendert. So werden „Blitzeffekte“ reduziert, bei denen Inhalte kurz sichtbar sind, bevor sie gesperrt werden. Außerdem werden unnötige Ressourcen (Skripte, Bilder, Komponenten) nicht geladen. Das ist für Nutzererlebnis und Performance die sinnvollste Platzierung.

Q3: Was, wenn die Anfrage an https://my.ipin.io/info fehlschlägt?

Die häufigste Strategie ist „standardmäßig erlauben“, damit ein Ausfall einer externen API keine normalen Nutzer fälschlich sperrt. Eine andere Strategie ist „standardmäßig sperren“, passend für strenge Compliance-Szenarien. Du kannst je nach Risiko entscheiden. In beiden Fällen gilt: Logik simpel halten – wenn country erfolgreich kommt, prüfen; wenn nicht, die Standard-Policy anwenden.

Q4: Gibt es CORS-Probleme?

Möglich. Wenn die API keine Cross-Origin-Zugriffe aus dem Browser zulässt, wird fetch vom Browser blockiert. Dann musst du sicherstellen, dass die API CORS aktiviert (z. B. deine Domain erlaubt), sonst kann der Browser das zurückgegebene JSON nicht lesen. Für einen „Frontend-first“-Ansatz ist CORS der wichtigste Punkt, den du vorab prüfen solltest.

Q5: Welcher Standard ist der country-Wert?

Üblicherweise ist es ein zweibuchstabiger Länder-/Regionscode (oft ISO 3166-1 alpha-2). TW ist ein typisches Beispiel. In der Praxis empfiehlt es sich, durchgehend Großbuchstaben zu verwenden und die Blacklist im gleichen Format zu pflegen, um Fehlmatches durch Groß-/Kleinschreibung zu vermeiden.

Q6: Wie wechsle ich von „ein Land sperren“ zu „nur bestimmte Länder erlauben“?

Einfach die Logik umkehren:
- allowlist: nur ["US","JP"] erlauben, für alle anderen „Zugriff verweigert/Fehlermeldung“ anzeigen
- blocklist: nur ["TW"] sperren, alle anderen zulassen
Beides läuft darauf hinaus, zu prüfen, ob country in einer Liste enthalten ist – der Unterschied liegt im Standardverhalten.