Odoo är nåbart från det öppna internet på våra fem webbplatser, och det är inget undantag utan det normala: Den som driver ett erbjudande, en webbutik eller en kundinloggning har en offentlig server. Ett enda sårbart lösenord, en bortglömd konfigurationsfil eller en alltför generös behörighet räcker för att en offentlig server ska bli en öppen.
Det här inlägget visar hur du säkrar Odoo 19 på rätt sätt — inte med en enda åtgärd, utan med flera lager som kompletterar varandra: brandvägg och reverse proxy, vår öppen källkod-modul Web RBL, tvåfaktorsautentisering, lösenordspolicy och behörigheter — och vilka angreppsförsök var och en av dem faktiskt fångar upp. Till sist följer en steg-för-steg-anvisning som kan följas för varje egen Odoo-installation.
Innehåll i det här inlägget
- Försvar på djupet: varför en enda åtgärd aldrig räcker
- Lager 1: brandvägg och reverse proxy
- Lager 2: Web RBL — bryggan till brandväggen
- Lager 3: säkra Odoo självt (2FA, lösenordspolicy, behörigheter)
- Lager 4: databas och drift
- Inloggningsvägen i sin helhet
- Angreppsscenarier och hur man möter dem
- Steg-för-steg-anvisning
- Vanliga frågor
Försvar på djupet: varför en enda åtgärd aldrig räcker
Varje enskild säkerhetsåtgärd har en lucka. En brandvägg ser inte vad som händer i ett Odoo-inloggningsformulär. Ett starkt lösenord skyddar inte om det redan har stulits någon annanstans. En behörighetsstruktur hjälper inte mot en angripare som ännu inte har loggat in alls. Principen som stänger dessa luckor heter försvar på djupet (defense in depth): flera oberoende lager, där vart och ett för sig skulle kunna kringgås — men alla tillsammans inte.
Hos oss är det fyra lager, vart och ett med en egen uppgift:
- Brandvägg / reverse proxy — håller uppenbart skadligt borta innan det ens når servern
- Web RBL — förbinder båda sidor: Odoo lär sig av sin egen applikationslogg det som brandväggen inte alls kan se, och matar tillbaka det till den
- Odoo självt — tvåfaktorsautentisering, lösenordspolicy, behörigheter, sessionshantering
- Databas & drift — säkerhetskopiering, åtkomstskydd för administrationen, hemligheter utanför varje logg
I följande avsnitt går vi igenom varje lager för sig.
Lager 1: brandvägg och reverse proxy
Brandväggen är den första instans som ser en förfrågan, och den enda som kan hålla en angripare borta från varje tjänst på servern — inte bara från webbplatsen, utan även från e-postservern, VPN-åtkomsten och det egna administrationsgränssnittet. Vad som är meningsfullt att aktivera här beror på tillverkaren, men byggstenarna är desamma hos OPNsense, pfSense, HAProxy, FortiGate, Sophos eller Check Point:
| Funktion | Vad den hjälper mot |
|---|---|
| Aktuell TLS-version och begränsade krypteringsmetoder | Avlyssning och manipulation av anslutningen; föråldrade metoder har i flera år ansetts vara brutna eller svaga |
| Rykt- och ursprungslistor (RBL) | Kända angripar-nät, Tor-utgångsnoder, hela länder utan egna kunder — se nedan |
| Hastighetsbegränsning per adress | Provning av lösenord och katalogskannrar som ställer dussintals förfrågningar på några sekunder |
| Åtskillnad mellan administration och datatrafik | Själva brandväggens gränssnitt får inte vara nåbart via samma adress som den offentliga webbplatsen |
| IDS/IPS (intrångsdetektering/-skydd) | Kända angreppsmönster på nätverksnivå, oavsett vilken applikation som körs bakom |
| Automatiska säkerhetsuppdateringar för själva brandväggen | En ouppdaterad brandvägg är inte längre en brandvägg, utan ett ytterligare mål |
RBL-listor: standardvägen för att leverera rykte
RBL står för Real-time Blackhole List, ett begrepp från e-postvärlden: en adress per rad, hämtbar via HTTP, omladdad regelbundet. Praktiskt taget varje brandvägg kan läsa in en sådan lista och bygga regler av den — OPNsense och pfSense som URL Table Alias, HAProxy som ACL-fil, FortiGate som External Block List, Palo Alto som External Dynamic List, Cisco, Sophos, Juniper och MikroTik med egna namn på samma princip.
Just här sätter vår egen modul in — och just här börjar det andra lagret.
Lager 2: Web RBL — bryggan mellan applikation och brandvägg
En brandvägg ser paket, inte applikationslogik. Den vet inte att en förfrågan mot /xmlrpc/2/common är ett inloggningsförsök, att tjugo olika sökvägar på fjorton sekunder är en skanner, eller att en adress just nu lyckats gissa ett lösenord. Allt detta vet bara Odoo självt. Web RBL, vår egen modul med öppen källkod (AGPL-3), gör den kunskapen användbar — för Odoo självt och, levererad som RBL-lista, även för brandväggen framför.
Hotlistor avstäms löpande, var och en med egen nivå.
Kort sammanfattat det som beskrivs utförligt i det föregående inlägget:
- Mönsterigenkänning i sökvägar:
.env-filer,.git-kataloger, konfigurationsfiler, WordPress- och PHP-sonder, path traversal, kommandokörning via nya AI-gränssnitt - Inloggningsskydd som räknar över omstarter — till skillnad från Odoos egen räknare som lever i arbetsminnet
- Poängsättning av varje adress från 0 till 100, med motivering i klartext
- Felkonfigurationer (QNAP, Autodiscover, Synology) identifieras och blockeras aldrig, eftersom en spärr inte åtgärdar felet utan bara döljer det
- Främmande hotlistor som Spamhaus, FireHOL och Tor-utgångsnoder, avstäms löpande
- Tillåtelselista för adresser som aldrig ska blockeras
För det här inlägget är två egenskaper särskilt viktiga, eftersom de hänger direkt samman med brandväggen och med inloggningen.
En trög lista är en lista man kan lita på
Tillåtelselistan — adresser som aldrig blockeras, till exempel egna platsanslutningar — ändras i regel sällan. Just det är dess värde, inte dess brist: När en stillsam lista knappt rör sig på flera dagar märks varje sällsynt ändring omedelbart. Den dagliga automatiska uppdateringen finns inte för att mycket skulle ändras, utan för att den sällsynta ändringen inte ska behöva föras in för hand — och just där är det man glömmer. En av våra egna felkonfigurationer förra månaden uppmärksammades precis så: inte genom många händelser, utan genom den enda som ingen kände till, tills en kunds QNAP-webb-API felaktigt blockerades. Sedan dess står QNAP på listan över felkonfigurationer som aldrig blockeras utan bara rapporteras.
Inloggningen är platsen som en brandvägg inte ser
En brandvägg kan blockera en adress. Den kan inte veta om en inloggning lyckades, och än mindre om den kom från en adress som nyss ännu letade efter inloggningsuppgifter. Web RBL kan: En poäng över ett inställbart tröskelvärde förbjuder inloggningen helt, och en lyckad inloggning från en påfallande adress rapporteras — det är länken till nästa lager.
Lager 3: säkra Odoo självt
Tvåfaktorsautentisering: en andra hemlighet som inte går att återanvända
Lösenords största problem är inte deras kvalitet, utan att de återanvänds. Ett lösenord som har stulits hos en annan tjänst fungerar hos oss precis lika bra, så länge det är detsamma. Tvåfaktorsautentisering (2FA, även kallad TOTP) ställer en andra hemlighet mot detta: en sexsiffrig kod som ändras var trettionde sekund och beräknas utifrån en hemlighet som bara den egna smartphonen känner till. Ett stulet lösenord räcker då inte längre ensamt.
Odoo 19 Community har detta inbyggt — som installerbar modul Two-Factor Authentication (TOTP), kompletterad med ett reservalternativ via e-post. Varje användare ställer in det själv, via QR-kod, med valfri vanlig autentiseringsapp:
Inställningen: skanna QR-koden, bekräfta den sexsiffriga koden en gång, klart.
Men det hjälper bara dem som ställer in det själva — och erfarenheten visar att det utan tvång förblir en minoritet. Odoo har därför en tvingande policy: antingen bara för medarbetare (interna användare) eller för alla, inklusive portalanvändare. Utan en inställd andra hemlighet kommer ingen längre förbi inloggningsformuläret utan att åtminstone bekräfta via e-postkod.
Lösenordspolicy: en minimilängd är ingen självklarhet
Utan tilläggsmodul förlitar sig Odoo Community inte på någon minimilängd för lösenord — en användare kan ange ett lösenord på tre tecken om ingen hindrar det. Modulen Password Policy stänger just den luckan: en minimilängd som tillämpas på serversidan, inte bara föreslås i webbläsaren. Den som vill ha mer — en tvingande giltighetstid, en historik mot återanvändning — behöver en OCA- eller tredjepartsmodul för det; Community-versionen är medvetet hållen slimmad.
Behörigheter: bara den som behöver det får åtkomst
Odoo skiljer som standard på tre nivåer: portalanvändare (bara den egna kund- eller leverantörsportalen), interna användare (backend, med rättigheter per applikation) och administratörer (obegränsad åtkomst inklusive tekniska inställningar). Det vanligaste felet är inte ett för svagt lösenord, utan en alltför generöst tilldelad administratörsroll: Den som bara ska skapa fakturor behöver ingen åtkomst till systeminställningarna.
Två grundsatser bär den största delen av lasten:
API-nyckel i stället för lösenord: varje extern anslutning (bokföringsprogram, tidrapportering, egna skript) får en egen nyckel som när som helst kan återkallas, aldrig användarens lösenord.
Båda går att kontrollera i samma vy där tvåfaktorsautentiseringen ställs in:
En översikt, fyra spakar: lösenord, andra faktor, API-nycklar, inloggade enheter.
Sessioner och enheter: vem är inloggad just nu
Samma vy visar också från vilka enheter ett konto just nu är inloggat — och gör det möjligt att logga ut en enskild eller alla på en gång. Efter en förlorad bärbar dator eller vid misstanke om ett komprometterat lösenord är det det snabbaste verksamma steget: Sessionen upphör omedelbart, oavsett om lösenordet redan har ändrats.
Lager 4: databas och drift
Det fjärde lagret är det minst synliga och samtidigt det mest oförlåtliga, eftersom ett fel här kan göra allt som byggts upp tidigare om intet.
/web/database/manager ett gränssnitt där databaser kan skapas, säkerhetskopieras, återställas och raderas — skyddat endast av ett enda huvudlösenord. Det här gränssnittet ska enbart vara nåbart internt eller stängas av helt.
- Regelbundna, kontrollerade säkerhetskopior, lagrade åtskilt från själva servern. En säkerhetskopia som aldrig har återställts är ett antagande, inte en säkerhetskopia.
- Hemligheter hör inte hemma i någon loggfil. Lösenord, API-nycklar, licensuppgifter — den som skriver egna tillägg bör behandla dem som huvudlösenordet självt: logga dem ingenstans, inte heller ”bara för felsökning”.
- Håll modulerna uppdaterade, även och särskilt tredjepartsmoduler. Fria tilläggsmoduler (OCA och andra) ligger naturligt efter nya Odoo-versioner; före varje installation är det värt att se efter vilka beroenden som kommer med automatiskt.
Inloggningsvägen i sin helhet
De fyra lagren verkar inte efter varandra i skilda rum, utan på samma förfrågan, steg för steg. Med en inloggning som exempel blir det tydligast:
Fem ställen där en skadlig förfrågan kan sluta innan den når själva målet — och bara ett enda där en behörig användare klarar dem alla.
Angreppsscenarier och hur man möter dem
Följande översikt kopplar verkliga angreppsmönster till de lager som faktiskt stoppar dem. Flera av dem är inte teori, utan egna observationer under sjutton dagars verklig trafik på våra fem webbplatser.
| Angreppsscenario | Hur det går till | Vad som stoppar det |
|---|---|---|
| Provning av lösenord | Ett skript provar hundratals kombinationer mot inloggningsformuläret eller XML-RPC | Hastighetsbegränsning i brandväggen, Web RBL-räknare över omstarter, spärr efter tio försök, omedelbar spärr vid ignorerat vänta-meddelande |
| Återanvända inloggningsuppgifter stulna någon annanstans | Angriparen känner redan till användarnamn och lösenord — från en annan, hackad tjänst | Tvåfaktorsautentisering stoppar inloggningen trots korrekt lösenord; Web RBL rapporterar dessutom en lyckad inloggning från påfallande adress |
| Sökning efter kvarglömda hemligheter | Automatiserade förfrågningar efter .env, .git, molnåtkomstnycklar — hos oss 57 721 förfrågningar på sjutton dagar enbart efter .env |
Web RBL blockerar vid första träffen; brandväggen får därefter adressen som RBL-post för alla andra tjänster också |
| Katalog- och sökvägsskannrar | Dussintals påhittade sökvägar på några sekunder, på jakt efter bortglömda applikationer | Beteendeigenkänning: många felsidor, knappt någon träff, på kort tid — oavsett om sökvägen träffar ett känt mönster |
| Felkonfigurerad egen enhet | En synkroniseringsklient eller ett e-postprogram pekar av misstag på fel adress och knackar på varje minut | Identifiering som felkonfiguration i stället för som angrepp, ärende i stället för spärr — spärren skulle inte åtgärda felet, bara förskjuta det |
| Automatiserad insamling av obligatoriska uppgifter | En insamlare hämtar impressum-sidor under främmande stavningar, ofta som förberedelse för en våg av varningsbrev | Den kanoniska sökvägen förblir alltid nåbar (juridiskt nödvändigt), främmande stavningar identifieras och rapporteras eller blockeras |
| Förlorad eller stulen enhet | En inloggad bärbar dator eller mobiltelefon hamnar i orätta händer | Sessionsöversikt med omedelbar utloggning av alla enheter, oberoende av lösenordet |
| För vid intern behörighet | Ett användarkonto med fler rättigheter än nödvändigt komprometteras eller missbrukas | Minsta nödvändiga rättighet per applikation begränsar skadan på förhand till det kontot verkligen behöver |
| Missbruk av ett externt gränssnitt | En stulen API-nyckel eller ett komprometterat tredjepartssystem får åtkomst via XML-RPC/JSON-RPC | Egna, återkallbara API-nycklar i stället för användarlösenord; Web RBL övervakar även misslyckade RPC-inloggningar |
| Felbedömd sökmotor-crawler | En legitim crawler genererar så mycket trafik att den ser ut som en distribuerad angripare — på en av våra webbplatser var det över sjuttio procent av hela trafiken, orsakad av GPTBot | Tillåtelselista med de publicerade adressintervallen för kända sökmotorer förhindrar en felaktig spärr som skulle ta bort den egna webbplatsen ur indexeringen |
| Föråldrad tredjepartsmodul med känt säkerhetshål | Ett säkerhetshål i en fri tilläggsmodul blir offentligt, uppdateringen kommer först veckor senare | Före varje installation kontrollera vad som kommer med automatiskt; uppdateringar först på en testinstans, inte på det öppna hjärtat |
| Öppen databashantering | Administrationsgränssnittet är nåbart via det öppna internet; ett gissat eller svagt huvudlösenord räcker för att radera eller kopiera databaser | Gränssnittet exponeras aldrig offentligt, huvudlösenordet förblir långt, slumpmässigt och antecknas ingenstans |
Steg för steg: säkra den egna Odoo-installationen
Följande ordning är den vi själva skulle följa — från största effekt till finaste inställning.
1. Tvinga fram tvåfaktorsautentisering
- Om det inte redan är installerat: öppna Appar, sök efter ”Two-Factor Authentication” och installera (vid flera webbplatser rekommenderas dessutom ”Two-Factor Authentication by Mail” som reservalternativ).
- Öppna Inställningar → Allmänna inställningar → Behörigheter.
- Aktivera ”Kräv tvåfaktorsautentisering”.
- Välj policy: ”Endast medarbetare” för interna användare, ”Alla användare” om även portalanvändare (kunder med åtkomst) ska ingå.
- Spara. Från nästa inloggningsförsök kräver Odoo av varje användare utan inställd andra hemlighet åtminstone e-postkoden, tills autentiseringsappen har ställts in.
2. Fastställ en minimilängd för lösenord
- Öppna Appar, sök efter ”Password Policy” och installera.
- Öppna Inställningar → Allmänna inställningar → Behörigheter.
- Ange ”Lösenordets minimilängd” — tolv tecken är ett rimligt utgångsvärde.
- Spara. Regeln gäller från och med nu för varje ny eller ändrad lösenordstilldelning, inte retroaktivt för befintliga lösenord.
3. Gå igenom behörigheterna
- Öppna Inställningar → Användare & företag → Användare.
- Öppna varje användare för sig och kontrollera fliken med åtkomsträttigheter per applikation: Behöver personen verkligen ”Chef” eller ”Administratör”, eller räcker ”Användare”?
- Kontrollera särskilt: Vem har åtkomst till ”Inställningar” själva? Det bör vara en mycket liten grupp.
- För varje extern anslutning (bokföring, egna skript, tidrapportering) skapa under fliken ”Kontosäkerhet” för respektive teknisk användare en egen API-nyckel, i stället för att lämna ut användarens lösenord.
4. Installera Web RBL och observera innan det slås på på riktigt
- Lägg modulen från github.com/Alex0176/odoo-web-rbl i addon-sökvägen och installera.
- Observera i några dagar: menyn Web RBL → Utvärdering visar vilka mönster som faktiskt slår till.
- Först därefter slå på
web_rbl.sperren_aktiv(Inställningar → Tekniskt → Systemparametrar) — från och med här avvisas identifierade sonder på riktigt. - Koppla in spärrlistan i brandväggen som RBL-lista, under den adress som anges i modulen och skyddas med token (för OPNsense/pfSense som URL Table Alias, för HAProxy som ACL-fil).
5. Säkra själva brandväggen
- Gör brandväggens administrationsgränssnitt enbart nåbart från det interna nätverket, aldrig via samma offentliga adress som webbplatsen.
- Aktivera automatiska säkerhetsuppdateringar för brandväggens programvara, om tillverkaren erbjuder det.
- Kontrollera TLS-konfigurationen: endast aktuella protokollversioner, inaktivera föråldrade krypteringsmetoder.
- Om möjligt: koppla in en känd ryktelista (till exempel Spamhaus DROP) direkt i brandväggen — oberoende av Web RBL, eftersom brandväggen då också ser trafik till tjänster som Odoo aldrig når.
6. Stäng databashanteringen
- Kontrollera om
/web/database/managerär nåbart utifrån — om så är fallet, sättlist_db = Falsei Odoo-konfigurationen eller spärra sökvägen på brandväggsnivå. - Sätt databashanteringens huvudlösenord långt och slumpmässigt och anteckna det ingenstans där någon annan kan läsa det.
7. Kontrollera säkerhetskopian, ställ inte bara in den
- Ställ in en automatisk, regelbunden säkerhetskopia, lagrad åtskilt från Odoo-servern.
- Återställ den minst en gång på riktigt och kontrollera om återställningen fungerar — en okontrollerad säkerhetskopia är ett antagande.
Inget av dessa steg ersätter något av de andra. Den som bara genomför ett av dem har förstärkt en dörr och lämnat alla andra öppna — den som genomför alla sju har ett försvar som håller även när ett enskilt lager sviker.
Vad den här arkitekturen inte ersätter
Ingen av de beskrivna åtgärderna gör omsorgsfullhet överflödig. En modul som avvisar .env-sonder gör en av misstag publicerad .env-fil inte ofarlig. Tvåfaktorsautentisering skyddar inte mot en användare som läser upp sin kod för en uppringare i telefon. Och en brandvägg ersätter inget beslut om vem som faktiskt behöver vilken behörighet. En säkerhetsarkitektur skapar förutsättningar där ett enskilt fel inte genast blir en incident — den befriar ingen från omsorgsfullheten.
Vanliga frågor
Räcker ett starkt lösenord för att säkra Odoo 19?
Nej. Ett lösenord kan stjälas någon annanstans, helt oavsett dess kvalitet, och fungerar då hos varje tjänst som godtar samma lösenord. Först kombinationen med tvåfaktorsautentisering, en brandvägg framför och en vettig behörighetsstruktur ger ett skydd som håller även efter ett stulet lösenord.
Hur aktiverar jag tvåfaktorsautentisering i Odoo 19?
Installera modulen ”Two-Factor Authentication (TOTP)” via apphanteringen, aktivera sedan tvånget under Inställningar → Allmänna inställningar → Behörigheter och välj mellan ”Endast medarbetare” och ”Alla användare”. Därefter ställer varje användare in sin egen andra faktor via QR-kod.
Vad är en RBL-lista, och varför behöver Odoo en?
RBL (Real-time Blackhole List) är en adresslista hämtbar via HTTP som praktiskt taget varje brandvägg kan läsa in. Odoo levererar ingen sådan lista självt — vår modul Web RBL stänger den luckan genom att identifiera angreppstrafik i den egna applikationsloggen och lämna tillbaka den som RBL-lista till brandväggen framför.
Är Odoo 19 Community tillräckligt säkrat utan tilläggsmoduler?
Inte fullständigt. Utan modulen Password Policy finns ingen minimilängd för lösenord, utan Two-Factor Authentication ingen andra faktor, och utan en modul som Web RBL upptäcker Odoo varken sonderingsförsök eller upprepade inloggningsförsök över en omstart. Alla fyra går att komplettera kostnadsfritt.
Tillgänglighet
Web RBL är offentligt tillgänglig under AGPL-3 och körs hos oss i produktion på fem webbplatser:
github.com/Alex0176/odoo-web-rbl
Den fullständiga funktionsbeskrivningen med alla mönster, poängsättningen och hotlistorna finns i det föregående inlägget: Web RBL – spärrlista för angreppstrafik på de egna webbplatserna.
Frågor, kommentarer och felrapporter tar vi gärna emot — helst som issue på GitHub.