copied
// api documentation
IP Check API
Public JSON API & embeddable widget
Free with API key · VPN/proxy detection · ASN lookup · geolocation
response time<50ms cached
daily quota10k–1M req
corsany origin
// drop-in html widget
recommended
self-contained · copy-paste ready
The simplest way: paste this snippet into any HTML page. Pure HTML + inline CSS + vanilla JS — no dependencies, no iframes, no build step. Replace YOUR_API_KEY with your ipk_ key.
html · 1 file · zero deps
<!-- IP Check widget — cloud.mkntw.org -->
<div id="ipmk-widget">
  <div class="ipmk-head">
    <span>your ip</span>
    <a href="https://cloud.mkntw.org" target="_blank" rel="noopener">cloud.mkntw.org</a>
  </div>
  <div class="ipmk-body">
    <span class="ipmk-ip"></span>
    <span class="ipmk-flag"></span>
  </div>
  <div class="ipmk-meta"></div>
  <div class="ipmk-sub"></div>
  <div class="ipmk-tags"></div>
</div>
<style>
#ipmk-widget{font-family:ui-monospace,'SF Mono',Menlo,monospace;background:#14161b;color:#e4e6ea;
border:1px solid rgba(255,255,255,.09);padding:18px 20px;max-width:420px;display:flex;flex-direction:column;gap:10px}
#ipmk-widget .ipmk-head{display:flex;justify-content:space-between;font-size:9px;letter-spacing:.08em;
text-transform:uppercase;color:#80848c;padding-bottom:8px;border-bottom:1px solid rgba(255,255,255,.09)}
#ipmk-widget .ipmk-head a{color:#3ad577;text-decoration:none}
#ipmk-widget .ipmk-body{display:flex;align-items:baseline;gap:12px;min-height:28px}
#ipmk-widget .ipmk-ip{font-size:24px;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
#ipmk-widget .ipmk-flag{font-size:22px;line-height:1}
#ipmk-widget .ipmk-meta{font-size:11px;color:#a8acb5}
#ipmk-widget .ipmk-sub{font-size:10px;color:#80848c;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#ipmk-widget .ipmk-tags{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px}
#ipmk-widget .ipmk-tag{padding:2px 7px;border:1px solid rgba(255,255,255,.09);font-size:9px;
color:#80848c;text-transform:uppercase;letter-spacing:.04em}
#ipmk-widget .ipmk-tag.on{border-color:rgba(255,98,98,.4);color:#ff6262}
#ipmk-widget .ipmk-tag.warn{border-color:rgba(245,183,64,.4);color:#f5b740}
#ipmk-widget .ipmk-tag.ok{border-color:rgba(58,213,119,.4);color:#3ad577}
@media(prefers-color-scheme:light){
  #ipmk-widget{background:#fff;color:#1a1d24;border-color:rgba(0,0,0,.11)}
  #ipmk-widget .ipmk-head{color:#6a6f78;border-color:rgba(0,0,0,.11)}
  #ipmk-widget .ipmk-head a{color:#008a3e}
  #ipmk-widget .ipmk-meta{color:#4a4f58}
  #ipmk-widget .ipmk-sub{color:#6a6f78}
  #ipmk-widget .ipmk-tag{border-color:rgba(0,0,0,.11);color:#6a6f78}
  #ipmk-widget .ipmk-tag.on{border-color:rgba(184,48,48,.4);color:#b83030}
  #ipmk-widget .ipmk-tag.warn{border-color:rgba(138,92,0,.4);color:#8a5c00}
  #ipmk-widget .ipmk-tag.ok{border-color:rgba(0,138,62,.4);color:#008a3e}
}
</style>
<script>
(function(){
  var KEY = 'YOUR_API_KEY'; // replace with your ipk_... key
  var r = document.getElementById('ipmk-widget');
  function q(s){return r.querySelector(s)}
  fetch('https://cloud.mkntw.org/api/v1/lookup',{headers:{'X-API-Key':KEY}})
    .then(function(x){return x.json()})
    .then(function(d){
      if(d.error){q('.ipmk-ip').textContent='error';q('.ipmk-meta').textContent=d.error;return}
      q('.ipmk-ip').textContent = d.ip || '—';
      q('.ipmk-flag').textContent = d.flag || '';
      q('.ipmk-meta').textContent = [d.city,d.country].filter(Boolean).join(', ');
      q('.ipmk-sub').textContent = d.isp || d.org || '';
      var tags = q('.ipmk-tags');
      function t(txt,cls){var s=document.createElement('span');s.className='ipmk-tag'+(cls?' '+cls:'');s.textContent=txt;tags.appendChild(s)}
      if(d.is_vpn||d.is_proxy) t('VPN','on');
      else if(d.is_hosting) t('HOSTING','warn');
      else t('DIRECT','ok');
      if(d.is_mobile) t('MOBILE');
    })
    .catch(function(){q('.ipmk-ip').textContent='error'});
})();
</script>
// live preview
your ip cloud.mkntw.org
// script injector
iframe-based · use for csp isolation
html
<script src="https://cloud.mkntw.org/embed.js" defer></script>
<div data-ipcheck
     data-theme="auto"
     data-key="ipk_your_key"
     data-height="180"></div>
// direct iframe
no javascript required
html
<iframe src="https://cloud.mkntw.org/embed?theme=dark"
        width="420" height="180"
        frameborder="0"></iframe>
// json api
requires X-API-Key
GET /api/v1/lookup
GET https://cloud.mkntw.org/api/v1/lookup
authX-API-Key header or ?key= query
cors* any origin
rate limitdaily quota + 60/min burst per IP
cache5 min per-IP (X-Cache header)
headersX-RateLimit-Limit, X-RateLimit-Remaining
javascript fetch
const res = await fetch('https://cloud.mkntw.org/api/v1/lookup', {
  headers: { 'X-API-Key': 'ipk_your_key_here' }
});
const data = await res.json();
console.log(data.ip, data.country, data.is_vpn);
curl
curl https://cloud.mkntw.org/api/v1/lookup \
  -H "X-API-Key: ipk_your_key_here"
example response
{
  "ip": "1.2.3.4",
  "country": "Germany",
  "country_code": "DE",
  "flag": "🇩🇪",
  "region": "Berlin",
  "city": "Berlin",
  "timezone": "Europe/Berlin",
  "isp": "Deutsche Telekom AG",
  "asn": "AS3320",
  "is_vpn": false,
  "is_proxy": false,
  "is_hosting": false,
  "is_mobile": false,
  "cached": true,
  "server_time": "2026-04-07T16:30:00.000Z"
}
// security rules engine
free · 10k/day
drop-in ip access control · block by country / asn / isp / city / vpn
Protect your site from unwanted traffic in one line. Create a project, add blocking rules, drop a <script> tag. Visitors matching a rule get a modal, a redirect, or a custom handler.
step 1 · create a project
Use the playground below (easiest) or call the API directly:
curl
curl -X POST https://cloud.mkntw.org/api/v1/register \
  -H "Content-Type: application/json" \
  -d '{"domain":"yoursite.com","name":"My Site"}'
response
{
  "token": "tok_abc123...",
  "domain": "yoursite.com",
  "quota_daily": 10000
}
Save the token — you need it for all following requests. Keep it client-safe (can be exposed in frontend code).
step 2 · add rules
curl · add block_country rule
curl -X POST https://cloud.mkntw.org/api/v1/rules \
  -H "X-Project-Token: tok_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"type":"block_country","value":"RU","reason":"regional restriction"}'
Supported rule types:
block_ipExact IPv4 match, e.g. 1.2.3.4
block_countryISO 2-letter code, e.g. RU, CN, IR
block_cityCity name, case-insensitive, e.g. Moscow
block_regionRegion/state name, e.g. California
block_asnASN format AS12345
block_ispISP substring match, e.g. DigitalOcean
block_vpnBlock all proxy/VPN detected traffic (boolean)
block_hostingBlock traffic from hosting providers/datacenters
block_mobileBlock mobile carrier traffic
allow_ipWhitelist IP (overrides all block rules)
step 3 · drop-in protection (1 line)
Add one script tag to your HTML <head>. That's it.
html · drop-in guard
<script src="https://cloud.mkntw.org/guard.js"
        data-token="tok_your_token_here"
        defer></script>
The script checks the visitor's IP against your rules. If blocked, it shows a modal (default). No dependencies, ~3KB minified, cached 1h.
step 3b · framework integrations
Pick your stack — copy 2-5 lines. Everything else (IP detection, rule matching, blocking UI) runs on our API. Keep your token in .env / process.env for production.
Plain HTML 1 line
<script src="https://cloud.mkntw.org/guard.js"
        data-token="tok_..." defer></script>
React (Helmet) 3 lines
<Helmet>
  <script src="https://cloud.mkntw.org/guard.js"
    data-token={process.env.REACT_APP_IPMK} defer />
</Helmet>
Next.js (App Router) 2 lines
import Script from 'next/script';

<Script src="https://cloud.mkntw.org/guard.js"
  data-token={process.env.NEXT_PUBLIC_IPMK} strategy="afterInteractive" />
Vue 3 (onMounted) 5 lines
onMounted(() => {
  const s = document.createElement('script');
  s.src = 'https://cloud.mkntw.org/guard.js';
  s.dataset.token = import.meta.env.VITE_IPMK;
  document.head.appendChild(s);
});
Nuxt 3 (useHead) 3 lines
useHead({
  script: [{ src: 'https://cloud.mkntw.org/guard.js',
    'data-token': useRuntimeConfig().public.ipmk, defer: true }]
});
Svelte / SvelteKit 3 lines
<svelte:head>
  <script src="https://cloud.mkntw.org/guard.js"
    data-token={import.meta.env.VITE_IPMK} defer></script>
</svelte:head>
WordPress (functions.php) 3 lines
add_action('wp_head', function() {
  echo '<script src="https://cloud.mkntw.org/guard.js" data-token="'
    . getenv('IPMK_TOKEN') . '" defer></script>';
});
Laravel Blade 2 lines
{{-- resources/views/layouts/app.blade.php --}}
<script src="https://cloud.mkntw.org/guard.js"
  data-token="{{ env('IPMK_TOKEN') }}" defer></script>
Django template 2 lines
{# templates/base.html #}
<script src="https://cloud.mkntw.org/guard.js"
  data-token="{{ IPMK_TOKEN }}" defer></script>
Express (server-side) 5 lines
app.use(async (req, res, next) => {
  const ip = req.headers['x-forwarded-for']?.split(',')[0] || req.ip;
  const d = await fetch(`https://cloud.mkntw.org/api/v1/check?ip=${ip}`,
    { headers: { 'X-Project-Token': process.env.IPMK } }).then(r => r.json());
  d.allowed ? next() : res.status(403).send('Blocked');
});
Cloudflare Worker 5 lines
export default { async fetch(req, env) {
  const ip = req.headers.get('cf-connecting-ip');
  const d = await fetch(`https://cloud.mkntw.org/api/v1/check?ip=${ip}`,
    { headers: { 'X-Project-Token': env.IPMK } }).then(r => r.json());
  return d.allowed ? fetch(req) : new Response('Blocked', { status: 403 });
} };
Flask (Python) 5 lines
@app.before_request
def guard():
  ip = request.headers.get('X-Forwarded-For', request.remote_addr).split(',')[0]
  r = requests.get(f'https://cloud.mkntw.org/api/v1/check?ip={ip}',
    headers={'X-Project-Token': os.environ['IPMK']}).json()
  if not r.get('allowed'): abort(403)
.env pattern: Store IPMK_TOKEN=tok_... in your environment file. Server-side integrations keep the token private. Client-side tokens are safe to expose — they are domain-bound & rate-limited.
step 4 · choose a mode
mode="modal" — default. Shows a blocking modal dialog.
modal mode (default)
<script src="https://cloud.mkntw.org/guard.js"
        data-token="tok_..."
        data-mode="modal"
        data-title="Sorry, access denied"
        data-message="This content is not available in your region."
        defer></script>
mode="redirect" — redirects blocked users to a URL (with ?reason=...&country=...&ip=...).
redirect mode
<script src="https://cloud.mkntw.org/guard.js"
        data-token="tok_..."
        data-mode="redirect"
        data-redirect="/blocked.html"
        defer></script>

// See /blocked-demo for a ready-made blocked page template
// URL params sent: ?reason=block_country&country=RU&ip=1.2.3.4
mode="silent" — just adds data-ipmk-verdict="blocked" on <html>. Use CSS or JS to handle it.
silent mode + css
<script src="https://cloud.mkntw.org/guard.js"
        data-token="tok_..."
        data-mode="silent"
        defer></script>

<style>
html[data-ipmk-verdict=blocked] .premium-content { display: none; }
html[data-ipmk-verdict=blocked] .blocked-notice { display: block; }
</style>
mode="callback" — call a global function with the verdict. Full custom handling.
callback mode
<script>
window.handleBlock = function(verdict) {
  console.log('blocked:', verdict);
  // verdict.ip, verdict.country_code, verdict.matched_rule...
  alert('Blocked from ' + verdict.country);
};
</script>
<script src="https://cloud.mkntw.org/guard.js"
        data-token="tok_..."
        data-mode="callback"
        data-on-block="handleBlock"
        defer></script>
events · listen to allow/block
guard.js always dispatches ipmk:allowed and ipmk:blocked events on window.
javascript
window.addEventListener('ipmk:allowed', function(e) {
  console.log('Access allowed:', e.detail.ip);
});

window.addEventListener('ipmk:blocked', function(e) {
  console.log('Blocked:', e.detail.matched_rule);
  // e.detail = full verdict object
});
api reference · security endpoints
POST/api/v1/register
body{"domain":"...","name":"..."}
returnsproject token, quota info
limit5 registrations/day per IP
GET/api/v1/rules
headerX-Project-Token
returnsproject info, all rules, stats
POST/api/v1/rules
headerX-Project-Token
body{"type":"...","value":"...","reason":"..."}
limit500 rules/project, 20 creates/min
DELETE/api/v1/rules/:id
headerX-Project-Token
GET/api/v1/check
headerX-Project-Token
query?ip= (optional — uses client IP by default)
returnsallowed: bool, matched_rule, geo data
limit10,000 checks/day per project
// live playground
try it now
create a real project · add rules · check ips · runs on live api
Everything below makes real API calls. Your token is saved in localStorage so you can come back later. Use it with guard.js on your own site.
// no signup — token is saved locally in your browser
// example blocked page
ready-made template · point data-redirect here
When data-mode="redirect", blocked users land on a page with ?reason=...&country=...&ip=... query params. We ship a demo at /blocked-demo — you can use it as-is or copy the HTML to your own /blocked.html.
// how the protection works
live flow
step-by-step · real bot detection in production
Here is exactly what happens when a visitor loads your page with guard.js installed. Each verified session receives a unique verification ID like ipmk-a1b2c3 for tracking and stats.
flow diagram · 7 stages
1. loadBrowser loads your HTML → guard.js executes → hits /api/v1/check with your token
2. geoServer resolves visitor IP → country, ASN, ISP, VPN/hosting/mobile flags
3. rulesMatches against your project rules (country / asn / isp / hosting / vpn / custom IP)
4. verdictReturns {allowed: bool, matched_rule: ..., ip, country, ...}
5. actionIf blocked → modal / redirect / callback based on data-mode
6. challengeRedirect mode sends user to /challenge → PoW + fingerprint collection
7. sessionOn success: verification_id issued, cookie set, auto-redirect back
verification id · what it binds
ipSession only valid from the same IP that solved challenge
user-agentSHA-256 hash of UA; UA change invalidates session
fingerprintCanvas + WebGL + Audio + navigator hash; hardware change invalidates
ttl1 hour rolling expiration
hit trackingEvery /api/v1/challenge/check increments hit_count
stats api · monitoring
GET/api/v1/session/stats
returns{active_sessions, total_issued, total_hits, banned_ips}
GET/api/v1/session/info
authcookie ipmk_session or X-Session header
returnsYour session: verification_id, issued_at, hit_count, fp_bound
// real install example · safevpn.su
live in production
how safevpn.su itself is protected right now
safevpn.su is a real Vue 3 SPA served from nginx. Here is the exact integration used today — copy and adapt.
step 1 · register project, get token
curl
curl -X POST https://cloud.mkntw.org/api/v1/register \
  -H "Content-Type: application/json" \
  -d '{"domain":"safevpn.su","name":"SafeVPN production"}'

# Response: {"token":"tok_xxx","domain":"safevpn.su","quota_daily":10000,...}
step 2 · add blocking rules
curl · block datacenter traffic
# block all hosting providers (blocks 99% of bots)
curl -X POST https://cloud.mkntw.org/api/v1/rules \
  -H "X-Project-Token: tok_xxx" \
  -H "Content-Type: application/json" \
  -d '{"type":"block_hosting","value":"true","reason":"datacenter bots"}'

# whitelist your own server IP so admin tools work
curl -X POST https://cloud.mkntw.org/api/v1/rules \
  -H "X-Project-Token: tok_xxx" \
  -H "Content-Type: application/json" \
  -d '{"type":"allow_ip","value":"YOUR_SERVER_IP","reason":"admin"}'
step 3 · add guard to your index.html
html · before </head>
<!-- Callback handler: redirect to challenge on block -->
<script>
window.__ipmkBlocked = function(v) {
  console.warn('[ipmk] blocked:', v);
  // Redirect to challenge, return to current URL after success
  location.href = 'https://cloud.mkntw.org/challenge?to=https://yoursite.com' +
    encodeURIComponent(location.pathname + location.search);
};
</script>

<script src="https://cloud.mkntw.org/guard.js"
        data-token="tok_your_token"
        data-mode="callback"
        data-on-block="__ipmkBlocked"
        defer></script>
</head>
what happens on user visit
real user→ guard.js checks IP → allowed: true → page renders normally
bot (hosting IP)matched_rule: block_hosting__ipmkBlocked() → redirect to /challenge
at challengeSolves PoW, collects fingerprint → verification_id issued
headless browserFingerprint flagged as automation → HTTP 403 + IP ban 1h
pure http botNo JS execution → never reaches guard.js → served only static HTML (no app data)
check your stats anytime
curl
# Public aggregate stats (no PII)
curl https://cloud.mkntw.org/api/v1/session/stats
# → {"active_sessions":42,"total_issued":1280,"banned_ips":3,...}

# Your project rules + hit stats
curl -H "X-Project-Token: tok_xxx" \
  https://cloud.mkntw.org/api/v1/rules
# → {"total_rules":2,"stats":{"total_checks":847,"total_blocks":62,...}}
// challenge & bot protection
cloudflare-style
proof-of-work interstitial · session cookies · bot scoring
Gate any page behind a browser verification step. Like Cloudflare's "Checking your browser": users solve a SHA-256 PoW challenge in their browser, receive a signed session cookie, and are redirected to the content. Bots without JS/WebCrypto fail automatically.
how it works
1. requestClient hits protected URL without valid session cookie
2. redirectServer sends them to /challenge?to=/original
3. powBrowser solves SHA-256 puzzle (~15k iterations, ~100ms)
4. verifyServer validates HMAC-signed challenge + PoW solution
5. sessionHMAC-bound session cookie set (1 hour, IP + UA locked)
6. redirectBrowser lands on original URL — protected content served
try it
endpoints
POST/api/v1/challenge/issue
returns{challenge, signature, difficulty, issued_at}
POST/api/v1/challenge/verify
body{challenge, signature, solution}
returns{session, expires_at, expires_in}
GET/api/v1/challenge/check
headerX-Session or ?session=sess_...
returns{valid: bool} — locked to IP + UA
GET/api/v1/bot-score
returns{bot_score: 0-100, verdict: bot|suspicious|likely_human}
signalsUA, Accept-Language, Sec-Fetch-*, Sec-CH-UA headers
integration · nginx reverse proxy
Gate any URL behind /challenge using cookie check in nginx:
nginx · /etc/nginx/sites-enabled/yoursite
server {
  listen 443 ssl;
  server_name yoursite.com;

  # Gate premium pages behind challenge
  location /premium/ {
    if ($cookie_ipmk_session = "") {
      return 302 https://cloud.mkntw.org/challenge?to=$scheme://$host$request_uri;
    }
    # Serve normal content
    proxy_pass http://backend;
  }
}
integration · client-side spa
javascript
// Check session on page load, redirect to challenge if missing
if (!document.cookie.includes('ipmk_session=')) {
  location.href = 'https://cloud.mkntw.org/challenge?to=' + encodeURIComponent(location.href);
}
integration · express middleware
node.js
app.use(async (req, res, next) => {
  const sid = req.cookies.ipmk_session;
  if (!sid) {
    return res.redirect(`https://cloud.mkntw.org/challenge?to=${encodeURIComponent(req.originalUrl)}`);
  }
  const r = await fetch(`https://cloud.mkntw.org/api/v1/challenge/check`, {
    headers: { 'X-Session': sid, 'User-Agent': req.headers['user-agent'] }
  }).then(r => r.json());
  r.valid ? next() : res.redirect('https://cloud.mkntw.org/challenge');
});
// server hardening guides
vps / linux / windows
copy-paste commands to secure your vps
Production-ready snippets for Ubuntu/Debian VPS, Nginx, and Windows Server. Each block is a drop-in recipe you can paste into your terminal or config.
ssh hardening · key-only auth, no root, rate limit
bash · /etc/ssh/sshd_config.d/hardening.conf
# Drop into /etc/ssh/sshd_config.d/hardening.conf
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers deploy  # replace with your user
Protocol 2

# Apply:
sudo sshd -t && sudo systemctl restart ssh
ufw firewall · deny all, allow only what you need
bash
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp   # ssh
sudo ufw allow 80/tcp   # http
sudo ufw allow 443/tcp  # https
sudo ufw limit 22/tcp   # rate limit ssh attempts
sudo ufw enable
sudo ufw status verbose
fail2ban · auto-ban brute force attempts
bash · /etc/fail2ban/jail.local
sudo apt install -y fail2ban

# /etc/fail2ban/jail.local
cat <<EOF | sudo tee /etc/fail2ban/jail.local
[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 3
backend  = systemd

[sshd]
enabled = true

[nginx-http-auth]
enabled = true

[nginx-botsearch]
enabled = true
EOF

sudo systemctl enable --now fail2ban
sudo fail2ban-client status
unattended upgrades · auto security patches
bash
sudo apt install -y unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades

# Verify config:
cat /etc/apt/apt.conf.d/50unattended-upgrades | grep -E 'Automatic-Reboot|Mail'
ssl/tls · let's encrypt + strong ciphers
bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d yoursite.com -d www.yoursite.com
sudo certbot renew --dry-run   # verify auto-renewal

# Strong DH params (generate once, takes ~5 min):
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
nginx · security headers + rate limiting
nginx · conf.d
# /etc/nginx/conf.d/security.conf
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()" always;
add_header Content-Security-Policy "default-src 'self'" always;

# Rate limit zones
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

# Usage in server block:
# location /api/ { limit_req zone=api burst=20 nodelay; }
# location /login { limit_req zone=login burst=5; }

# Hide nginx version
server_tokens off;
secrets management · .env, permissions, rotation
bash
# Create .env with strict permissions
touch /opt/myapp/.env
chmod 600 /opt/myapp/.env
chown myapp:myapp /opt/myapp/.env

# Generate strong random secrets:
openssl rand -hex 32    # 256-bit for JWT/HMAC
openssl rand -base64 48 # 384-bit for sessions

# systemd service: load from file, not exposed
# EnvironmentFile=/opt/myapp/.env
# NoNewPrivileges=true
# ProtectSystem=strict
# PrivateTmp=true
docker security · non-root, read-only, no-new-privs
docker-compose.yml
services:
  app:
    image: myapp
    user: "1000:1000"
    read_only: true
    tmpfs: [ /tmp, /run ]
    cap_drop: [ ALL ]
    security_opt:
      - no-new-privileges:true
    restart: unless-stopped
    ports: [ "127.0.0.1:8080:8080" ]  # bind to localhost only
windows server · powershell hardening
powershell
# Disable SMBv1 (legacy, insecure)
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart

# Disable weak TLS versions, enforce TLS 1.2+
New-Item "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" -Force
Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" Enabled 0

# Windows Firewall: default block inbound
Set-NetFirewallProfile -Profile Domain,Public,Private -DefaultInboundAction Block
New-NetFirewallRule -DisplayName "Allow RDP" -Direction Inbound -LocalPort 3389 -Protocol TCP -Action Allow -RemoteAddress "1.2.3.4"
New-NetFirewallRule -DisplayName "Allow HTTPS" -Direction Inbound -LocalPort 443 -Protocol TCP -Action Allow

# Enable Windows Defender features
Set-MpPreference -DisableRealtimeMonitoring $false
Set-MpPreference -PUAProtection Enabled
Set-MpPreference -MAPSReporting Advanced

# Account lockout after 5 failed logins
net accounts /lockoutthreshold:5 /lockoutduration:30 /lockoutwindow:30
cryptography · safe algorithms, correct usage
hashingUse argon2id for passwords, never md5/sha1 alone
symmetricAES-256-GCM with random IV, never ECB mode
asymmetricEd25519 or RSA-4096 for signing, ECDH for key exchange
tokensHMAC-SHA256 with 32+ byte secret, constant-time compare
randomnessAlways crypto.randomBytes(), never Math.random()
storageEnv vars or secret manager, never in git
transportTLS 1.2+ only, HSTS preload, certificate pinning for mobile
// error responses
http status · error code · meaning
401api_key_required — missing X-API-Key header
401invalid_key — key not in store
401invalid_key_format — must start with ipk_
401revoked — key was revoked
429quota_exceeded — daily quota reached, see reset_at
429burst_limit — 60 req/min per IP exceeded
502geo_lookup_failed — upstream geo service error
// get an api key
manual issuance · free
Contact @mkntw on Telegram with your domain and use case. Default quota: 10,000 requests/day. Keys can be revoked at any time. No signup, no dashboard — just a token.