Aller au contenu

Configuration de proxy (accès restreint / sans internet)

Repod est entièrement utilisable avec zéro accès internet — rien de ce qu'il fait ne nécessite de connectivité sortante par défaut. Mais une poignée de fonctionnalités optionnelles contactent des sources publiques, et si votre serveur se trouve derrière une sortie réseau restreinte (une équipe sécurité qui n'autorise que des domaines spécifiques, ou un site entièrement air-gap), vous devez savoir exactement quoi autoriser — et comment le router à travers un proxy.

Cette page liste chaque dépendance sortante, explique comment les router à travers un proxy d'entreprise, et donne un exemple concret utilisant Squid avec une liste blanche de domaines, le modèle déjà utilisé par la plupart des environnements réglementés pour un contrôle de sortie maîtrisé.


Ce qui nécessite réellement un accès internet

Rien dans le pipeline central upload → scan → publication → service ne nécessite d'accès internet. Tout ce qui suit est soit optionnel, soit déclenché uniquement par une action spécifique.

Dépendance Déclenchée par Peut fonctionner entièrement hors-ligne ?
Mises à jour de signatures ClamAV Automatique (démon freshclam) Oui — fonctionne avec les signatures déjà en cache ; seules les mises à jour nécessitent une connexion
Base de vulnérabilités Grype Automatique, périodique Oui — pareil que ci-dessus, la correspondance CVE utilise la dernière base téléchargée avec succès
Scores EPSS / catalogue CISA KEV Chaque scan CVE Oui — cache local 24h ; un paquet déjà scanné une fois continue de fonctionner hors-ligne
Synchronisation de sécurité amont (avis de sécurité Debian/Ubuntu/RPM) Job de synchronisation planifié (désactivé par défaut) N/A — cette fonctionnalité concerne intrinsèquement la récupération d'avis externes
« Import depuis internet » (miroirs de paquets amont, Maven Central, PyPI, npmjs.org, Docker Hub) Action utilisateur explicite (onglet « Import ») N/A — utilisé uniquement si vous choisissez d'importer depuis une source publique
Cache amont (proxy pull-through pour les clients apt/dnf) Requêtes clientes vers /upstream/... N/A — voir Cache amont, une fonctionnalité séparée orientée air-gap
Remontée d'usage de licence Opt-in uniquement (settings["license_reporting"]["enabled"]) Oui — la validation de licence est 100% hors-ligne ; la remontée est purement informative
Notifications LDAP / OIDC / SMTP / webhook Selon ce que vous configurez Dépend entièrement de l'emplacement de votre IdP/relais SMTP/point de terminaison webhook (souvent interne)

Si votre politique est « pas d'internet, un point c'est tout », le pipeline continue de fonctionner — les scans CVE et antivirus utilisent les données mises en cache lors de votre dernière fenêtre connectée (ou un cache air-gap amorcé depuis un hôte relais), et vous n'utilisez simplement jamais l'onglet « Import depuis internet ».


Router les appels sortants via un proxy

La majorité du tableau ci-dessus passe par du HTTP(S) simple depuis le conteneur backend, en utilisant des clients qui respectent les variables d'environnement de proxy standard. Définissez-les dans backend.env :

backend.env
HTTP_PROXY=http://proxy.internal.example.com:3128
HTTPS_PROXY=http://proxy.internal.example.com:3128
NO_PROXY=localhost,127.0.0.1,db,depot-apt,depot-rpm,YOUR_INTERNAL_LDAP_HOST

Ceci couvre : les appels d'enrichissement CVE/EPSS/KEV, la fonctionnalité « Import depuis internet » (miroirs amont, recherche Maven Central, PyPI, npmjs.org, Docker Hub), et les mises à jour de base de Grype lui-même — tous utilisent des clients HTTP qui honorent ces variables automatiquement, sans configuration supplémentaire nécessaire.

Le freshclam de ClamAV est l'unique exception

freshclam ne lit pas HTTP_PROXY/HTTPS_PROXY — il ne comprend que ses propres directives de configuration. Si vous avez besoin que les mises à jour ClamAV passent par un proxy explicite (non transparent), montez une surcharge freshclam.conf :

freshclam.conf
HTTPProxyServer proxy.internal.example.com
HTTPProxyPort 3128
docker-compose.override.yaml
services:
  backend:
    volumes:
      - ./freshclam.conf:/etc/clamav/freshclam.conf:ro

Si votre proxy est déployé en mode transparent/interception au niveau réseau (voir ci-dessous), cette surcharge n'est pas nécessaire — freshclam ne sait pas qu'il est proxifié de toute façon.


Exemple concret : Squid avec une liste blanche de domaines

Plutôt qu'un proxy généraliste « tout autoriser », la plupart des environnements réglementés veulent une liste blanche explicite — seulement les domaines dont Repod a réellement besoin, rien d'autre. L'ACL dstdomain de Squid est l'outil standard pour ceci.

1. Fichier de liste blanche

squid/allowed_domains.txt
# Security feeds
api.first.org
www.cisa.gov

# ClamAV / Grype update infrastructure — consult their own docs for the
# current full list, these CDN domains do change over time
database.clamav.net
.cvdupdate.clamav.net
grype.anchore.io
toolbox-data.anchore.io

# OS package mirrors — only the ones matching the distributions you serve
archive.ubuntu.com
security.ubuntu.com
deb.debian.org
security.debian.org
dl-cdn.alpinelinux.org
repo.almalinux.org
dl.rockylinux.org
mirror.stream.centos.org
download.opensuse.org

# Build-tool ecosystems — only if you use "Import from internet" for these
repo1.maven.org
search.maven.org
pypi.org
registry.npmjs.org
hub.docker.com
registry-1.docker.io
production.cloudflare.docker.com

2. squid.conf

squid/squid.conf
http_port 3128

acl allowed_domains dstdomain "/etc/squid/allowed_domains.txt"
acl repod_net src 172.20.0.0/16   # adjust to your Docker network / server subnet

http_access allow repod_net allowed_domains
http_access deny all

# Standard hardening
via off
forwarded_for delete
request_header_access X-Forwarded-For deny all

3. L'exécuter (autonome, ou en overlay compose)

docker-compose.proxy.yaml
services:
  squid:
    image: ubuntu/squid:latest
    container_name: repod-squid
    ports:
      - "127.0.0.1:3128:3128"   # bind to loopback; only the Repod host should reach it
    volumes:
      - ./squid/squid.conf:/etc/squid/squid.conf:ro
      - ./squid/allowed_domains.txt:/etc/squid/allowed_domains.txt:ro
    restart: unless-stopped
docker compose -f docker-compose.proxy.yaml up -d

Puis pointez backend.env vers celui-ci :

backend.env
HTTP_PROXY=http://squid:3128
HTTPS_PROXY=http://squid:3128

(Si squid tourne sur le même réseau Docker que backend, utilisez le nom du service comme nom d'hôte ; sinon utilisez le port de proxy de l'hôte.)

4. Vérifier

# From inside the backend container:
docker exec backend-api curl -sI https://api.first.org
# Should succeed (allowlisted)

docker exec backend-api curl -sI https://example.com
# Should be denied by Squid (not on the allowlist)

Surveillez docker logs repod-squid (ou le access.log de Squid) pendant que vous déclenchez un scan CVE ou un « Import depuis internet » — tout domaine légitimement nécessaire qui serait refusé apparaîtra ici comme TCP_DENIED, vous permettant d'étendre la liste blanche délibérément plutôt que de deviner à l'avance.


Entièrement air-gap (aucun proxy du tout)

Si le serveur n'a vraiment aucun chemin sortant — pas même via un proxy — voir Cache amont pour amorcer des miroirs de paquets via un support amovible à travers un hôte relais, et s'appuyer sur les caches locaux EPSS/KEV/Grype/ClamAV pour les données CVE et antivirus (rafraîchies manuellement pendant une fenêtre de maintenance avec connectivité, si une telle fenêtre existe un jour — sinon le pipeline continue d'utiliser ce qui était en cache au moment du déploiement).