Direct publiceren via IIS (zonder DMZ)
Deze handleiding beschrijft hoe u de SQLio API's direct kunt publiceren via IIS, zonder gebruik te maken van een DMZ met reverse proxy. Dit is een eenvoudigere configuratie die geschikt is voor MKB-omgevingen.
In deze configuratie wordt IIS URL Rewrite gebruikt om te bepalen welke paden extern toegankelijk zijn. Alleen de API endpoints, Swagger documentatie en login pagina worden doorgelaten. De beheer UI blijft afgeschermd voor externe toegang.
Na configuratie zijn alleen de volgende paden extern bereikbaar:
| URL | Toegankelijk | Bescherming |
|---|---|---|
/api/* |
✅ Ja | Basic Auth + API Key |
/api-login |
✅ Ja | Login formulier |
/api-docs |
✅ Ja | Basic Auth login vereist |
/swagger/* |
✅ Ja | Basic Auth login vereist |
/ (UI) |
❌ Nee | Geblokkeerd door URL Rewrite |
/webhooks |
❌ Nee | Geblokkeerd door URL Rewrite |
/environment-configuration |
❌ Nee | Geblokkeerd door URL Rewrite |
/datasets |
❌ Nee | Geblokkeerd door URL Rewrite |
Deze configuratie biedt meerdere beveiligingslagen:
| Laag | Wat het doet |
|---|---|
| 1. URL Rewrite | Alleen /api/*, /api-login, /api-docs extern bereikbaar |
| 2. Rate Limiting | Maximaal aantal requests per IP per tijdseenheid |
| 3. IP Whitelist | Optioneel: alleen bekende IP-adressen toestaan |
| 4. Basic Auth | Login vereist voor Swagger documentatie |
| 5. API Key | Elke API call vereist een geldige API key |
| 6. HTTPS | Alle verkeer versleuteld |
| Component | Versie / Details |
|---|---|
| Windows Server | 2016 of hoger |
| IIS | Geïnstalleerd met ASP.NET Core Hosting Bundle |
| URL Rewrite Module | 2.1 of hoger |
| Dynamic IP Restrictions | IIS Feature (voor rate limiting) |
| SQLio | Geïnstalleerd en werkend |
| SSL Certificaat | Geldig certificaat voor HTTPS |
Download de URL Rewrite Module van de officiële Microsoft website:
https://www.iis.net/downloads/microsoft/url-rewrite
Of installeer via PowerShell:
# Download en installeer URL Rewrite $url = "https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi" Invoke-WebRequest -Uri $url -OutFile "rewrite.msi" Start-Process msiexec.exe -ArgumentList '/i rewrite.msi /quiet' -Wait
Na installatie verschijnt URL Rewrite in IIS Manager onder de site features.
De URL Rewrite regels bepalen welke paden extern toegankelijk zijn. Voeg de volgende regels toe aan de web.config in de SQLio root folder.
Voeg het volgende toe binnen de <system.webServer> sectie:
<rewrite>
<rules>
<!-- Regel 1: API paden toestaan (geen actie) -->
<rule name="Allow API paths" stopProcessing="false">
<match url="^(api/|api-login|api-docs|swagger)" />
<action type="None" />
</rule>
<!-- Regel 2: Blokkeer niet-API paden voor externe IP's -->
<rule name="Block external non-API" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<!-- Niet van intern netwerk -->
<add input="{REMOTE_ADDR}"
pattern="^(192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|127\.0\.0\.1)"
negate="true" />
<!-- En niet een toegestaan API pad -->
<add input="{REQUEST_URI}"
pattern="^/(api/|api-login|api-docs|swagger)"
negate="true" />
</conditions>
<action type="CustomResponse"
statusCode="403"
statusReason="Forbidden"
statusDescription="Access denied from external network" />
</rule>
</rules>
</rewrite>
| Stap | Wat er gebeurt |
|---|---|
| 1 | Regel 1 checkt of de URL begint met api/, api-login, api-docs of swagger |
| 2 | Als ja: geen actie (request gaat door naar applicatie) |
| 3 | Regel 2 checkt of het IP-adres NIET van het interne netwerk komt |
| 4 | Als extern EN niet een API pad: blokkeer met 403 Forbidden |
192.168.x.x, 10.x.x.x en 172.16-31.x.x. Pas dit aan als uw netwerk andere ranges gebruikt.
Als u alleen specifieke externe IP-adressen wilt toestaan (bijv. van partners of klanten), kunt u een whitelist toevoegen.
Voeg deze regel toe vóór de "Block external non-API" regel:
<!-- Optionele IP whitelist voor API toegang -->
<rule name="IP Whitelist for API" stopProcessing="true">
<match url="^api/" />
<conditions logicalGrouping="MatchAll">
<!-- Niet van intern netwerk -->
<add input="{REMOTE_ADDR}"
pattern="^(192\.168\.|10\.|127\.0\.0\.1)"
negate="true" />
<!-- Niet op de whitelist -->
<add input="{REMOTE_ADDR}"
pattern="^(203\.0\.113\.50|198\.51\.100\.25|85\.12\.34\.56)$"
negate="true" />
</conditions>
<action type="CustomResponse"
statusCode="403"
statusReason="Forbidden"
statusDescription="IP address not allowed" />
</rule>
Voeg IP-adressen toe aan de pattern, gescheiden door | (pipe):
pattern="^(203\.0\.113\.50|198\.51\.100\.25|nieuw\.ip\.adres)$"
\. in plaats van .). Dit is vereist in XML configuratie.
Rate limiting beschermt tegen brute force aanvallen en DDoS. IIS heeft ingebouwde Dynamic IP Restrictions.
# Installeer IIS IP Security feature Install-WindowsFeature Web-IP-Security
Voeg toe binnen de <system.webServer> sectie:
<security>
<dynamicIpSecurity enableLoggingOnlyMode="false" enableProxyMode="false">
<!-- Blokkeer bij te veel gelijktijdige requests -->
<denyByConcurrentRequests enabled="true" maxConcurrentRequests="20" />
<!-- Blokkeer bij te veel requests per tijdseenheid -->
<denyByRequestRate enabled="true"
maxRequests="50"
requestIntervalInMilliseconds="10000" />
</dynamicIpSecurity>
</security>
| Setting | Waarde | Toelichting |
|---|---|---|
maxConcurrentRequests |
20 | Max gelijktijdige requests per IP |
maxRequests |
50 | Max requests per interval |
requestIntervalInMilliseconds |
10000 | 10 seconden interval |
enableLoggingOnlyMode |
false | Daadwerkelijk blokkeren (niet alleen loggen) |
Hieronder staat een complete web.config sectie met alle beveiligingslagen gecombineerd. Voeg dit toe aan of merge met de bestaande web.config in de SQLio folder.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<!-- Rate Limiting -->
<security>
<dynamicIpSecurity enableLoggingOnlyMode="false">
<denyByConcurrentRequests enabled="true"
maxConcurrentRequests="20" />
<denyByRequestRate enabled="true"
maxRequests="50"
requestIntervalInMilliseconds="10000" />
</dynamicIpSecurity>
</security>
<!-- URL Rewrite: alleen API paden extern -->
<rewrite>
<rules>
<!-- Stap 1: API paden toestaan -->
<rule name="Allow API" stopProcessing="false">
<match url="^(api/|api-login|api-docs|swagger)" />
<action type="None" />
</rule>
<!-- Stap 2: Optionele IP whitelist voor API -->
<!--
<rule name="IP Whitelist" stopProcessing="true">
<match url="^api/" />
<conditions logicalGrouping="MatchAll">
<add input="{REMOTE_ADDR}"
pattern="^(192\.168\.|10\.)" negate="true" />
<add input="{REMOTE_ADDR}"
pattern="^(203\.0\.113\.50)$" negate="true" />
</conditions>
<action type="CustomResponse" statusCode="403" />
</rule>
-->
<!-- Stap 3: Blokkeer rest voor externe IP's -->
<rule name="Block non-API external" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REMOTE_ADDR}"
pattern="^(192\.168\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|127\.0\.0\.1)"
negate="true" />
<add input="{REQUEST_URI}"
pattern="^/(api/|api-login|api-docs|swagger)"
negate="true" />
</conditions>
<action type="CustomResponse"
statusCode="403"
statusReason="Forbidden"
statusDescription="Access denied" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Na configuratie moet u testen of de beveiliging correct werkt.
| Test | Verwacht resultaat |
|---|---|
Browse naar https://sqlio.bedrijf.nl/ |
✅ SQLio UI (Windows Auth popup) |
Browse naar https://sqlio.bedrijf.nl/webhooks |
✅ Webhook pagina |
Browse naar https://sqlio.bedrijf.nl/api-docs |
✅ Swagger login of Swagger UI |
API call naar /api/test |
✅ 401 (zonder credentials) of 200 (met credentials) |
Test vanaf een extern IP-adres (bijv. via mobiel netwerk of externe server):
| Test | Verwacht resultaat |
|---|---|
Browse naar https://api.bedrijf.nl/ |
❌ 403 Forbidden |
Browse naar https://api.bedrijf.nl/webhooks |
❌ 403 Forbidden |
Browse naar https://api.bedrijf.nl/api-login |
✅ Login pagina |
Browse naar https://api.bedrijf.nl/api-docs |
✅ Redirect naar login pagina |
API call naar /api/test |
✅ 401 of 200 (afhankelijk van credentials) |
# PowerShell: stuur 100 requests snel achter elkaar
1..100 | ForEach-Object {
try {
Invoke-WebRequest -Uri "https://api.bedrijf.nl/api/test" -Method GET -TimeoutSec 5
} catch {
Write-Host "Request $_`: $($_.Exception.Response.StatusCode)"
}
}
# Na ~50 requests zou u 403 moeten krijgen
| Probleem | Mogelijke oorzaak | Oplossing |
|---|---|---|
| 403 op alle requests | URL Rewrite fout | Check regex patterns, controleer backslash escaping |
| UI bereikbaar van extern | Regel volgorde incorrect | Zorg dat Block regel NA Allow regel komt |
| Rate limit te snel bereikt | Waarden te laag | Verhoog maxRequests en interval |
| IP whitelist werkt niet | Pattern fout | Test regex op regex101.com |
| 500 errors | web.config syntax fout | Valideer XML syntax |
| Interne toegang geblokkeerd | IP range niet correct | Voeg uw interne IP range toe aan de pattern |
Schakel Failed Request Tracing in om te zien welke regels worden toegepast:
# In IIS Manager: # 1. Selecteer de SQLio site # 2. Klik op "Failed Request Tracing Rules" # 3. Klik "Add..." en voeg regel toe voor status code 403 # 4. Schakel Failed Request Tracing in (rechterkolom: "Edit Site Tracing") # 5. Logs staan in: %SystemDrive%\inetpub\logs\FailedReqLogFiles
Voeg tijdelijk logging toe om te zien welke regels matchen:
<!-- Voeg toe aan rewrite sectie voor debugging -->
<rewrite>
<rules>
<!-- Voeg logCondition toe aan uw regels -->
<rule name="Debug logging" stopProcessing="false">
<match url=".*" />
<serverVariables>
<set name="HTTP_X_DEBUG_IP" value="{REMOTE_ADDR}" />
<set name="HTTP_X_DEBUG_URI" value="{REQUEST_URI}" />
</serverVariables>
<action type="None" />
</rule>
<!-- ... rest van uw regels ... -->
</rules>
</rewrite>
C:\inetpub\logs\LogFiles voor gedetailleerde request informatie.