Ασφάλεια για τοπικά LLM: πώς ορίζετε πού επιτρέπεται να πηγαίνει η ΤΝ σας
technology

Ασφάλεια για τοπικά LLM: πώς ορίζετε πού επιτρέπεται να πηγαίνει η ΤΝ σας

Τα τοπικά μοντέλα είναι ιδιωτικά, όμως οι agents και τα εργαλεία τους βγαίνουν στο internet. Πώς φτιάχνετε δικούς σας κανόνες για το πού επιτρέπεται να φτάνει η ΤΝ σας, με Docker, VM, WireGuard ή δικό σας gateway.

29 Οκτωβρίου 2026
Theodoros Dimitriou

Η λειτουργία ενός γλωσσικού μοντέλου στον δικό σας υπολογιστή ή server είναι από τις καλύτερες επιλογές για την προστασία των δεδομένων. Τα prompts, τα έγγραφα και τα δεδομένα πελατών μένουν σε εσάς. Γι’ αυτό φτιάχνουμε τοπική ΤΝ για τους πελάτες μας, και γι’ αυτό και δικά μας εργαλεία όπως το LOKIDocs δουλεύουν χωρίς σύνδεση.

Όμως «τοπικό» δεν σημαίνει «εκτός σύνδεσης». Μόλις δώσετε σε ένα τοπικό μοντέλο εργαλεία, όπως αναζήτηση στο web, browser, τερματικό ή έναν MCP server, αρχίζει να μιλά με το internet. Από εκεί και πέρα μια ερώτηση μετρά περισσότερο από την επιλογή του μοντέλου: σε ποιες διευθύνσεις επιτρέπεται να φτάνει η ΤΝ σας και σε ποιες όχι;

Αυτός ο οδηγός δείχνει πώς ο καθένας μπορεί να απαντήσει με δικούς του κανόνες: από μια ρύθμιση 15 λεπτών σε έναν υπολογιστή μέχρι ένα gateway για ολόκληρη ομάδα.

Ποιος βγαίνει τελικά στο internet;

Όχι το ίδιο το μοντέλο. Το Ollama, το LM Studio ή το llama.cpp εκτελούν το μοντέλο και μένουν σιωπηλά, εκτός από τη λήψη ενός μοντέλου όταν τη ζητήσετε. Η κίνηση έρχεται από ό,τι τρέχει γύρω από το μοντέλο:

  • τον agent που δίνει στο μοντέλο τα εργαλεία του (Claude Code, Open WebUI, ο δικός σας agent σε Python ή Node)
  • εργαλεία λήψης σελίδων και αναζήτησης στο web
  • MCP servers
  • διαχειριστές πακέτων όπως pip και npm, που ένας agent με τερματικό τρέχει πρόθυμα μόνος του
  • ένα απλό curl στο shell

Αυτή την κίνηση πρέπει να ελέγξετε. Και είναι ζήτημα δικτύου, όχι μοντέλου: κανένα prompt και καμία οδηγία συστήματος δεν εμποδίζει αξιόπιστα έναν agent να καλέσει μια διεύθυνση. Ένα firewall, ναι.

Το ένα όριο που πρέπει να ξέρετε: το HTTPS κρύβει το URL

Σχεδόν όλη η κίνηση είναι κρυπτογραφημένη. Στο δίκτυο βλέπετε το domain (github.com), όχι όμως την πλήρη διεύθυνση (github.com/myorg/project), τη μέθοδο ή το περιεχόμενο.

Έτσι προκύπτουν δύο επίπεδα κανόνων:

  • Κανόνες domain («μόνο pypi.org, github.com και ο δικός μας server»): απλοί, χωρίς αποκρυπτογράφηση, αρκετοί για τους περισσότερους.
  • Κανόνες URL και περιεχομένου («μόνο ο δικός μας οργανισμός στο GitHub», «ποτέ αποστολή ιδιωτικού κλειδιού»): το gateway πρέπει να αποκρυπτογραφεί την κίνηση. Γι’ αυτό δημιουργείτε μια δική σας μικρή αρχή πιστοποίησης (CA), την οποία εμπιστεύονται τα εργαλεία ΤΝ.

Αν επιλέξετε το δεύτερο επίπεδο, δύο πράγματα από πριν:

  • Τα Node, Python και Go συχνά αγνοούν το αποθετήριο πιστοποιητικών του συστήματος. Δείξτε τους τη CA σας με NODE_EXTRA_CA_CERTS, SSL_CERT_FILE και REQUESTS_CA_BUNDLE.
  • Εφαρμογές που «καρφώνουν» τα πιστοποιητικά τους (pinning) απορρίπτουν τις αποκρυπτογραφημένες συνδέσεις. Κρατήστε γι’ αυτές μια σύντομη λίστα που περνά μόνο με έλεγχο σε επίπεδο domain.

Τέσσερις τρόποι να «πιάσετε» την κίνηση

Προσέγγιση Πόσο ισχυρή Κόπος
Μεταβλητές περιβάλλοντος HTTP_PROXY Αδύναμη: κάθε εργαλείο μπορεί να τις αγνοήσει Λεπτά
VPN για όλη τη συσκευή Πιάνει τα πάντα, και τη δική σας περιήγηση Μικρός
Φίλτρο ανά εφαρμογή (π.χ. macOS Network Extension) Ισχυρή, μόνο οι διεργασίες ΤΝ Μεγάλος: χρειάζεται υπογραφή και δικαιώματα από την Apple
ΤΝ σε container, VM ή ξεχωριστό χρήστη, με μόνη έξοδο τον proxy ή το tunnel Η ισχυρότερη και η πιο κατανοητή Μέτριος

Προτείνουμε την τελευταία γραμμή. Η ιδέα: μη ζητάτε από την ΤΝ να χρησιμοποιήσει τον proxy. Δώστε της έναν χώρο όπου ο proxy είναι η μόνη έξοδος.

Επίπεδο 1: ένα φίλτρο σε 15 λεπτά με Docker

Για έναν υπολογιστή και κανόνες domain. Χρειάζεστε μόνο Docker.

Δύο δίκτυα: ένα εσωτερικό χωρίς διαδρομή προς το internet, όπου ζει ο agent, και ένα κανονικό. Μόνο ο proxy βρίσκεται και στα δύο.

# docker-compose.yml
services:
  proxy:
    image: ubuntu/squid
    volumes:
      - ./squid.conf:/etc/squid/squid.conf:ro
    networks: [ai-internal, internet]

  agent:
    image: python:3.12-slim      # or the image of your agent
    command: sleep infinity
    environment:
      HTTP_PROXY: http://proxy:3128
      HTTPS_PROXY: http://proxy:3128
      NO_PROXY: localhost,ollama
    networks: [ai-internal]

networks:
  ai-internal:
    internal: true               # no route to the internet
  internet: {}

Και η λίστα επιτρεπόμενων:

# squid.conf
http_port 3128
acl allowed dstdomain .pypi.org .files.pythonhosted.org .github.com
http_access allow allowed
http_access deny all

Τα εργαλεία που σέβονται τον proxy φτάνουν πλέον μόνο στα domains της λίστας. Όσα τον αγνοούν δεν φτάνουν πουθενά, γιατί το εσωτερικό δίκτυο δεν έχει έξοδο. Το Squid καταγράφει επίσης κάθε αίτημα, έτσι βλέπετε τι προσπάθησε ο agent σας.

Αν το μοντέλο σας τρέχει στο Ollama, βάλτε κι ένα container του Ollama στο εσωτερικό δίκτυο. Κατεβάστε τα μοντέλα πριν το κλειδώσετε ή προσθέστε το registry.ollama.ai στη λίστα.

Επίπεδο 2: μια VM, ένα tunnel και ένας διακόπτης ασφαλείας

Όταν ο agent πρέπει να τρέχει σαν κανονικό πρόγραμμα, με τερματικό και δικά του αρχεία, δώστε του μια εικονική μηχανή (UTM, Parallels, VirtualBox) ή ένα μικρό μηχάνημα Linux. Η VM στέλνει τα πάντα μέσα από ένα tunnel WireGuard στο gateway σας:

# /etc/wireguard/wg0.conf in the VM
[Interface]
PrivateKey = <private key of the VM>
Address = 10.66.0.2/32
DNS = 10.66.0.1                  # DNS only through the gateway

[Peer]
PublicKey = <public key of the gateway>
Endpoint = gateway.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0     # everything, IPv6 included

Το κρίσιμο σημείο είναι ο διακόπτης ασφαλείας (kill switch). Ένας agent με τερματικό θα μπορούσε απλώς να κλείσει το tunnel. Γι’ αυτό το firewall απορρίπτει ό,τι στέλνει ο χρήστης του agent εκτός tunnel:

# Kill switch for the user "aiagent": loopback and the tunnel only
iptables  -A OUTPUT -o lo  -m owner --uid-owner aiagent -j ACCEPT
iptables  -A OUTPUT -o wg0 -m owner --uid-owner aiagent -j ACCEPT
iptables  -A OUTPUT        -m owner --uid-owner aiagent -j REJECT
ip6tables -A OUTPUT -o lo  -m owner --uid-owner aiagent -j ACCEPT
ip6tables -A OUTPUT -o wg0 -m owner --uid-owner aiagent -j ACCEPT
ip6tables -A OUTPUT        -m owner --uid-owner aiagent -j REJECT

Για να αντέξει αυτό, δύο κανόνες:

  • Ο agent τρέχει ως aiagent χωρίς δικαιώματα διαχειριστή. Όποιος είναι root μπορεί να σβήσει και τους κανόνες του firewall. Αν ο agent χρειάζεται root, ο διακόπτης ασφαλείας μπαίνει στον host αντί για τη VM.
  • Το DNS και το IPv6 περνούν κι αυτά από το tunnel (DNS = και ::/0 παραπάνω). Αλλιώς γίνονται πίσω πόρτα.

Σε Mac χωρίς VM, το ίδιο γίνεται με ξεχωριστό χρήστη macOS και το ενσωματωμένο firewall pf, που μπορεί επίσης να φιλτράρει ανά χρήστη.

Επίπεδο 3: δικό σας gateway με κανόνες URL, καταγραφή και εισαγωγή κλειδιών

Τώρα το tunnel καταλήγει σε ένα gateway που ελέγχετε εσείς: ένας μικρός VPS, ένας server στο γραφείο ή ένα home lab. Αποκρυπτογραφεί, ελέγχει κάθε αίτημα με βάση τους κανόνες σας και καταγράφει το αποτέλεσμα.

[AI sandbox] ──WireGuard──▶ [Gateway server]
 kill switch                      │
 trusts your CA                   ▼
                       Proxy (decrypts TLS)
                                  │
                       Policy (YAML / Python)
                                  │
                 allowed → internet │ denied → 403 + log
                                  │
                         Audit log, dashboard

Γιατί αξίζει ένας ξεχωριστός server:

  • Δεν παραποιείται. Κανόνες και καταγραφές βρίσκονται εκεί όπου ο agent δεν μπορεί να τα αλλάξει, ακόμη κι αν γίνει root στο δικό του μηχάνημα.
  • Εισαγωγή κλειδιών. Το gateway προσθέτει τα πραγματικά κλειδιά API μόνο στην έξοδο. Ο agent έχει μόνο ψεύτικα, άρα δεν υπάρχει τίποτα να κλαπεί. Αυτό είναι ίσως το μεγαλύτερο κέρδος ασφάλειας.
  • Μία πολιτική για πολλά μηχανήματα, μία σταθερή IP εξόδου και μία κοινή καταγραφή.

Το γρηγορότερο ξεκίνημα είναι το mitmproxy, που έχει ενσωματωμένη λειτουργία WireGuard: το ξεκινάτε, σκανάρετε ή αντιγράφετε τη ρύθμιση WireGuard που εμφανίζει, συνδέετε τη VM, τέλος. Εγκαταστήστε τη CA του (~/.mitmproxy/mitmproxy-ca-cert.pem) στη VM και ορίστε τις τρεις μεταβλητές από πάνω. Οι κανόνες σας είναι ένα σύντομο αρχείο Python:

# policy.py, start with:  mitmdump --mode wireguard -s policy.py
import os, re
from mitmproxy import http

ALLOW = {                                  # host -> allowed path prefixes
    "pypi.org": ["/"],
    "files.pythonhosted.org": ["/"],
    "docs.python.org": ["/"],
    "api.github.com": ["/repos/myorg/"],   # only your own organisation
}
READ_ONLY = {"docs.python.org"}
SECRETS = re.compile(rb"-----BEGIN [A-Z ]*PRIVATE KEY-----|AKIA[0-9A-Z]{16}")

def request(flow: http.HTTPFlow) -> None:
    req = flow.request
    paths = ALLOW.get(req.pretty_host)
    if paths is None or not any(req.path.startswith(p) for p in paths):
        return block(flow, "host or path not allowed")
    if req.pretty_host in READ_ONLY and req.method != "GET":
        return block(flow, "read-only site")
    if req.content and SECRETS.search(req.content):
        return block(flow, "secret in request body")
    if req.pretty_host == "api.github.com":
        # the agent only has a dummy token; the real one is added here
        req.headers["Authorization"] = f"Bearer {os.environ['GITHUB_TOKEN']}"

def block(flow: http.HTTPFlow, reason: str) -> None:
    flow.response = http.Response.make(
        403, f"Blocked by AI policy: {reason}".encode(), {"Content-Type": "text/plain"})

Αργότερα μπορείτε να αντικαταστήσετε το mitmproxy με έναν μικρό proxy σε Go, ως ένα μόνο αρχείο, και τους κανόνες Python με ένα αρχείο YAML ή με OPA, όταν οι κανόνες σας μεγαλώσουν.

Κανόνες πέρα από το «επιτρέπεται» και «απαγορεύεται»

Μόλις το gateway βλέπει ολόκληρα αιτήματα, ανοίγουν πολλές δυνατότητες:

  • Μέθοδος και διαδρομή: μόνο GET σε σελίδες τεκμηρίωσης, κανένα POST σε άγνωστους hosts.
  • Έλεγχος διαρροής δεδομένων: μπλοκάρισμα αιτημάτων με μυστικά, περιεχόμενο .env ή ιδιωτικά κλειδιά.
  • Έλεγχος των API των LLM: ποια μοντέλα επιτρέπονται, όρια σε tokens ή κόστος, καταγραφή prompts και απαντήσεων.
  • Όρια ρυθμού και λειτουργία έγκρισης: ένα άγνωστο domain περιμένει μέχρι να το εγκρίνετε.
  • Έλεγχος απαντήσεων: επισήμανση σελίδων που περιέχουν μοτίβα prompt injection.

Κλείστε τις πίσω πόρτες

Ένα φίλτρο είναι τόσο καλό όσο η πιο αδύναμη διαδρομή του. Ελέγξτε:

  • DNS: DNS over HTTPS και απευθείας συνδέσεις σε διευθύνσεις IP. Περάστε όλο το DNS από το gateway σας.
  • QUIC / HTTP/3 στη θύρα UDP 443: μπλοκάρετέ το, τα προγράμματα γυρίζουν τότε σε TCP.
  • IPv6: φιλτράρετέ το όπως το IPv4 ή απενεργοποιήστε το.
  • WebSockets και άλλες συνδέσεις που μένουν ανοιχτές για πολύ.
  • Διαρροή μέσω επιτρεπόμενων domains: pastebins, gists, αποθήκευση στο cloud. Μια λίστα επιτρεπόμενων από μόνη της δεν το σταματά, μόνο ο έλεγχος περιεχομένου.

Ποιο επίπεδο σας ταιριάζει;

Η περίπτωσή σας Ξεκινήστε με
Δοκιμάζετε έναν agent στο laptop σας Επίπεδο 1
Ο agent έχει τερματικό ή δουλεύει με δεδομένα πελατών Επίπεδο 2
Πολλά μηχανήματα ή ομάδα, ή χρειάζεστε καταγραφή για ελέγχους Επίπεδο 3

Ξεκινήστε μικρά. Το Επίπεδο 1 στήνεται σε ένα απόγευμα και σας δείχνει ήδη πού θέλει να φτάσει η ΤΝ σας. Αυτή η λίστα είναι το καλύτερο σημείο εκκίνησης για κάθε αυστηρότερο κανόνα.

Χρειάζεστε βοήθεια;

Στήνουμε τοπική ΤΝ για μικρές και μεσαίες επιχειρήσεις: μοντέλα στο δικό σας hardware, βοηθούς που δουλεύουν με τα δεδομένα σας και κανόνες για το πού επιτρέπεται να πηγαίνει αυτή η ΤΝ. Αν θέλετε τοπική ΤΝ με σαφή όρια, πείτε μας τι θέλετε να τρέξετε ή διαβάστε περισσότερα για την ενσωμάτωση ΤΝ.