Si vous administrez des serveurs, écrivez des scripts d'automatisation ou déployez des applications dans une infrastructure d'entreprise, vous serez tôt ou tard confronté à la nécessité de faire passer le trafic curl ou wget par un proxy. Cela peut être un proxy d'entreprise, un contournement des géo-restrictions lors du téléchargement de paquets, ou la rotation des IP lors de requêtes massives vers des API externes. Dans cet article, nous nous concentrons uniquement sur la pratique : commandes, configurations, exemples de code sans fioritures.
1. Comment curl et wget fonctionnent avec des proxies : mécanismes de base
Avant de plonger dans les configurations, il est important de comprendre ce qui se passe sous le capot. Les deux outils supportent deux protocoles de proxy principaux : HTTP/HTTPS et SOCKS5. Leur mécanique est différente, et cela influence le type de proxy à choisir pour une tâche spécifique.
Le proxy HTTP fonctionne comme un intermédiaire au niveau du protocole applicatif. Lorsque curl envoie une requête via un proxy HTTP, il dit littéralement au serveur proxy : « fais une requête GET à cette URL à ma place ». Pour le trafic HTTPS, la méthode CONNECT est utilisée — curl demande au proxy d'établir un tunnel vers l'hôte cible, après quoi la poignée de main TLS se produit directement entre le client et le serveur de destination. C'est important : dans ce cas, le proxy ne voit pas le contenu du trafic HTTPS.
SOCKS5 fonctionne à un niveau plus bas — il proxy les connexions TCP/UDP sans lien avec le protocole de niveau applicatif. Cela rend SOCKS5 plus polyvalent : il peut gérer non seulement HTTP/HTTPS, mais aussi d'autres protocoles. De plus, SOCKS5 prend en charge la résolution DNS côté serveur proxy — ce qui est crucial pour éviter les fuites DNS.
💡 Différence clé pour la pratique :
Si vous devez simplement télécharger un fichier ou faire une requête API — un proxy HTTP suffit. Si vous avez besoin d'une anonymat complet, de contourner les fuites DNS ou de travailler avec des protocoles non standard — utilisez SOCKS5.
curl prend en charge les deux protocoles nativement depuis des versions très anciennes. wget a historiquement eu un support plus limité pour SOCKS5 — dans les anciennes versions (avant 1.19), il n'y a pas de support SOCKS5 du tout, seulement un proxy HTTP. Cela doit être pris en compte lors de l'écriture de scripts qui doivent fonctionner sur différentes distributions.
Pour vérifier la version de wget, utilisez la commande wget --version. Pour curl — curl --version, il sera également visible avec quels protocoles la bibliothèque libcurl a été compilée.
2. Variables d'environnement : le moyen le plus rapide de configurer
Le moyen le plus élégant de configurer un proxy pour curl et wget est via des variables d'environnement. Cela fonctionne de manière systémique : il n'est pas nécessaire de modifier chaque script, il suffit de définir les variables une fois dans la session ou de les ajouter au profil utilisateur.
Les deux outils lisent les mêmes variables standard :
# Pour le trafic HTTP export http_proxy="http://proxy.example.com:3128" # Pour le trafic HTTPS export https_proxy="http://proxy.example.com:3128" # Dupliquez en majuscules (certaines programmes ne lisent que celles-ci) export HTTP_PROXY="http://proxy.example.com:3128" export HTTPS_PROXY="http://proxy.example.com:3128" # Pour FTP (si nécessaire) export ftp_proxy="http://proxy.example.com:3128" # Exceptions — adresses qui NE passent PAS par le proxy export no_proxy="localhost,127.0.0.1,::1,192.168.0.0/16,.internal.company.com"
Un point important : curl est sensible à la casse des variables selon la version. Pour éviter les surprises — définissez toujours les deux versions : en minuscules et en majuscules. C'est une pratique standard en DevOps.
Pour que les paramètres soient appliqués en permanence pour un utilisateur spécifique, ajoutez les lignes dans ~/.bashrc ou ~/.profile. Pour les scripts système et les services — dans /etc/environment ou dans le fichier unitaire systemd via la directive Environment=.
# /etc/systemd/system/myservice.service
[Service]
Environment="http_proxy=http://proxy.example.com:3128"
Environment="https_proxy=http://proxy.example.com:3128"
Environment="no_proxy=localhost,127.0.0.1"
ExecStart=/usr/bin/myapp
Si le proxy nécessite une authentification, l'identifiant et le mot de passe sont insérés directement dans l'URL de la variable :
export http_proxy="http://username:[email protected]:3128" export https_proxy="http://username:[email protected]:3128"
⚠️ Sécurité :
Ne stockez pas les mots de passe en clair dans .bashrc ou dans les variables d'environnement sur les serveurs de production. Utilisez des solutions de coffre-fort (HashiCorp Vault, AWS Secrets Manager) ou au moins limitez les droits sur le fichier contenant les variables.
3. Flags curl pour travailler avec des proxies : analyse complète
curl fournit un riche ensemble de flags pour gérer les proxies directement depuis la ligne de commande. C'est pratique lorsque vous devez faire une requête ponctuelle via un proxy sans modifier les paramètres système.
Le flag principal est -x ou --proxy :
# Proxy HTTP de base curl -x http://proxy.example.com:3128 https://api.example.com/data # Forme courte curl -x proxy.example.com:3128 https://api.example.com/data # Avec indication explicite du protocole curl --proxy http://proxy.example.com:3128 https://api.example.com/data # Vérifier l'IP externe via le proxy curl -x http://proxy.example.com:3128 https://api.ipify.org
Pour ignorer les variables d'environnement et établir une connexion directe (contourner le proxy configuré), utilisez le flag --noproxy :
# Ignorer le proxy pour un hôte spécifique curl --noproxy "internal.company.com" https://internal.company.com/api # Ignorer complètement le proxy (même si les variables d'environnement sont définies) curl --noproxy "*" https://api.example.com/data
Flags utiles pour le débogage des connexions proxy :
# Mode verbose : toutes les en-têtes sont visibles, y compris CONNECT au proxy curl -v -x http://proxy.example.com:3128 https://api.example.com/data # Seulement les en-têtes de réponse curl -I -x http://proxy.example.com:3128 https://api.example.com/data # Afficher le temps de connexion via le proxy curl -w "Connect: %{time_connect}s\nTotal: %{time_total}s\n" \ -x http://proxy.example.com:3128 \ -o /dev/null -s https://api.example.com/data
Configurer le proxy via le fichier de configuration ~/.curlrc — pratique si vous ne souhaitez pas écrire les flags à chaque fois :
# ~/.curlrc
proxy = http://proxy.example.com:3128
proxy-user = username:password
noproxy = localhost,127.0.0.1,.internal.company.com
Pour les scripts système, vous pouvez créer un fichier de configuration séparé et le spécifier explicitement via curl -K /path/to/config — cela permet d'avoir différents profils de proxy pour différentes tâches.
4. Configuration du proxy dans wget : flags et fichier de configuration
wget est moins flexible que curl, mais pour des tâches typiques — téléchargement de fichiers, mirroring récursif de sites — ses capacités sont largement suffisantes. Le proxy dans wget peut être configuré de trois manières : via des variables d'environnement (déjà abordées), via des flags de ligne de commande et via le fichier de configuration ~/.wgetrc.
Flags de ligne de commande wget pour le proxy :
# Proxy HTTP via flag wget -e use_proxy=yes \ -e http_proxy=http://proxy.example.com:3128 \ https://example.com/file.tar.gz # HTTPS via proxy wget -e use_proxy=yes \ -e https_proxy=http://proxy.example.com:3128 \ https://example.com/file.tar.gz # Avec authentification wget -e use_proxy=yes \ -e http_proxy=http://username:[email protected]:3128 \ https://example.com/file.tar.gz # Désactiver le proxy pour une commande spécifique (si les variables d'environnement sont définies) wget --no-proxy https://internal.company.com/file.tar.gz
Le fichier de configuration ~/.wgetrc — méthode préférée pour une configuration permanente :
# ~/.wgetrc use_proxy = on http_proxy = http://proxy.example.com:3128 https_proxy = http://proxy.example.com:3128 ftp_proxy = http://proxy.example.com:3128 no_proxy = localhost,127.0.0.1,.internal.company.com # Si le proxy nécessite une authentification proxy_user = username proxy_password = secretpassword
Pour une application système (tous les utilisateurs), utilisez /etc/wgetrc — même format, mais appliqué globalement. Pratique pour les serveurs où toutes les opérations de téléchargement doivent passer par un proxy d'entreprise.
Exemple pratique : téléchargement récursif d'un site via un proxy avec une limite de profondeur et de vitesse :
wget -e use_proxy=yes \
-e http_proxy=http://proxy.example.com:3128 \
--recursive \
--level=2 \
--limit-rate=500k \
--wait=1 \
--random-wait \
--user-agent="Mozilla/5.0 (compatible; Googlebot/2.1)" \
https://example.com/docs/
5. Proxy SOCKS5 dans curl et wget : configuration et exemples
SOCKS5 est un protocole plus préféré pour les tâches où l'anonymat ou le travail avec des ports non standards est important. Pour les administrateurs système et les ingénieurs DevOps, SOCKS5 est souvent utilisé lors de l'utilisation de tunnels SSH, ainsi que lors de la connexion à des proxies résidentiels, qui imitent le trafic des utilisateurs réels.
Dans curl, SOCKS5 est pris en charge via un préfixe spécial dans l'URL du proxy :
# SOCKS5 avec résolution DNS côté client (peut entraîner une fuite DNS !) curl --socks5 proxy.example.com:1080 https://api.example.com/data # SOCKS5 avec résolution DNS côté proxy (recommandé !) curl --socks5-hostname proxy.example.com:1080 https://api.example.com/data # Via le flag -x avec indication explicite du protocole curl -x socks5h://proxy.example.com:1080 https://api.example.com/data # Avec authentification curl -x socks5h://username:[email protected]:1080 https://api.example.com/data # SOCKS5 via variable d'environnement export all_proxy="socks5h://proxy.example.com:1080" curl https://api.example.com/data
📌 socks5 vs socks5h — quelle est la différence ?
socks5 — la requête DNS est effectuée localement, seul le TCP passe par le proxy. Une fuite DNS est possible.socks5h (h = hostname) — la requête DNS est effectuée côté serveur proxy. Anonymat complet. Recommandé pour la plupart des tâches.
Un scénario populaire en DevOps est d'utiliser SSH comme proxy SOCKS5 pour faire passer le trafic via un bastion :
# Ouvrir un tunnel SSH avec SOCKS5 sur le port local 1080 ssh -D 1080 -f -C -q -N [email protected] # Maintenant, utilisez ce tunnel dans curl curl -x socks5h://localhost:1080 https://internal-api.private.network/data # Ou via une variable d'environnement pour toutes les requêtes dans la session export all_proxy="socks5h://localhost:1080" wget https://internal-resource.private.network/file.tar.gz
wget prend en charge SOCKS5 à partir de la version 1.19. Dans les versions plus anciennes (CentOS 7, Ubuntu 16.04), vous devrez utiliser des solutions de contournement : proxychains, tsocks, ou passer à curl pour les tâches nécessitant SOCKS5.
6. Authentification sur le proxy : identifiant et mot de passe
La plupart des proxies commerciaux et des serveurs proxy d'entreprise nécessitent une authentification. Il existe plusieurs façons de transmettre les informations d'identification — chacune avec ses avantages et inconvénients en termes de sécurité.
Méthode 1 : Informations d'identification dans l'URL — simple, mais peu sûr (le mot de passe est visible dans la liste des processus) :
curl -x http://user:p%[email protected]:3128 https://api.example.com/data # Les caractères spéciaux dans le mot de passe doivent être encodés en URL : @ → %40, : → %3A
Méthode 2 : Flag --proxy-user dans curl — le mot de passe peut ne pas être spécifié dans la ligne de commande, curl le demandera de manière interactive :
# Identifiant et mot de passe dans le flag (visible dans ps aux) curl -x http://proxy.example.com:3128 \ --proxy-user "username:password" \ https://api.example.com/data # Seulement l'identifiant — curl demandera le mot de passe de manière interactive curl -x http://proxy.example.com:3128 \ --proxy-user "username" \ https://api.example.com/data
Méthode 3 : Via le fichier .netrc — la plus sécurisée pour les scripts :
# ~/.netrc machine proxy.example.com login username password secretpassword # Limiter les droits d'accès au fichier chmod 600 ~/.netrc # Utiliser dans curl curl -x http://proxy.example.com:3128 --proxy-netrc https://api.example.com/data
Méthode 4 : Via des variables d'environnement depuis un coffre-fort secret — recommandé pour CI/CD et environnements de production :
# Dans le script, lire les informations d'identification depuis les variables (définies par CI/CD)
#!/bin/bash
PROXY_URL="http://${PROXY_USER}:${PROXY_PASS}@proxy.example.com:3128"
curl -x "${PROXY_URL}" https://api.example.com/data
Tableau comparatif des méthodes d'authentification :
| Méthode | Facilité | Sécurité | Convient pour |
|---|---|---|---|
| URL (user:pass@host) | ⭐⭐⭐ | ⭐ | Tests |
| Flag --proxy-user | ⭐⭐⭐ | ⭐⭐ | Commandes ponctuelles |
| Fichier .netrc | ⭐⭐ | ⭐⭐⭐ | Scripts locaux |
| Variables d'environnement depuis le coffre-fort | ⭐⭐ | ⭐⭐⭐⭐⭐ | CI/CD, production |
7. Exceptions et no_proxy : comment contourner le proxy pour les adresses locales
Dans les environnements d'entreprise et cloud, un réglage fin est souvent nécessaire : le trafic externe — via un proxy, interne — directement. La variable no_proxy (ou NO_PROXY) permet de définir une liste d'exceptions.
# Exceptions de base export no_proxy="localhost,127.0.0.1,::1" # Exception par domaine (avec point — tous les sous-domaines) export no_proxy="localhost,127.0.0.1,.internal.company.com,.corp.local" # Exception par plage IP (la notation CIDR ne fonctionne pas partout !) export no_proxy="localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" # Pour AWS : exclure le point de terminaison de métadonnées et les adresses internes export no_proxy="localhost,127.0.0.1,169.254.169.254,.amazonaws.com.internal"
⚠️ Caractéristique importante de no_proxy :
La notation CIDR (10.0.0.0/8) n'est pas prise en charge par tous les outils. curl la prend en charge à partir de la version 7.86.0. wget — ne la prend pas en charge du tout. Pour la compatibilité, il est préférable de lister des IP spécifiques ou des masques comme 10. (tout ce qui commence par 10.).
Exemple pratique pour un environnement Kubernetes, où il est nécessaire d'exclure le serveur API et les services internes :
export no_proxy="localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc,.default"
export NO_PROXY="${no_proxy}"
8. Proxy dans CI/CD : GitHub Actions, GitLab CI, Docker
Configurer un proxy dans les pipelines CI/CD est l'une des tâches les plus fréquentes pour les ingénieurs DevOps travaillant dans des réseaux d'entreprise ou avec un accès Internet limité. Examinons des configurations spécifiques pour des plateformes populaires.
GitHub Actions
# .github/workflows/deploy.yml
name: Déployer
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
env:
http_proxy: ${{ secrets.PROXY_URL }}
https_proxy: ${{ secrets.PROXY_URL }}
no_proxy: "localhost,127.0.0.1,.github.com"
steps:
- uses: actions/checkout@v3
- name: Télécharger les dépendances
run: |
curl -x "${http_proxy}" https://external-api.example.com/config.json -o config.json
wget -e use_proxy=yes -e http_proxy="${http_proxy}" https://releases.example.com/app-v1.0.tar.gz
GitLab CI
# .gitlab-ci.yml
variables:
http_proxy: "http://proxy.company.com:3128"
https_proxy: "http://proxy.company.com:3128"
no_proxy: "localhost,127.0.0.1,.gitlab.company.com"
build:
stage: build
script:
- curl -x "${http_proxy}" https://registry.npmjs.org/package -o package.json
- wget -e use_proxy=yes -e http_proxy="${http_proxy}" https://example.com/resource.tar.gz
Docker : proxy lors de la construction d'images
# Passer le proxy via les arguments de construction docker build \ --build-arg http_proxy=http://proxy.example.com:3128 \ --build-arg https_proxy=http://proxy.example.com:3128 \ --build-arg no_proxy=localhost,127.0.0.1 \ -t myapp:latest . # Dans le Dockerfile, utilisez ARG pour obtenir les variables
# Dockerfile FROM ubuntu:22.04 ARG http_proxy ARG https_proxy ARG no_proxy ENV http_proxy=${http_proxy} ENV https_proxy=${https_proxy} ENV no_proxy=${no_proxy} RUN apt-get update && apt-get install -y curl wget RUN curl -x "${http_proxy}" https://example.com/setup.sh | bash # Nettoyer les variables proxy dans l'image finale (optionnel) ENV http_proxy="" ENV https_proxy=""
Configuration globale du proxy pour le démon Docker (pour docker pull via le proxy) :
# /etc/systemd/system/docker.service.d/proxy.conf [Service] Environment="HTTP_PROXY=http://proxy.example.com:3128" Environment="HTTPS_PROXY=http://proxy.example.com:3128" Environment="NO_PROXY=localhost,127.0.0.1,.internal.registry.com" # Redémarrer docker systemctl daemon-reload systemctl restart docker
9. Rotation des proxies dans les scripts bash
Si vous devez faire un grand nombre de requêtes vers des API externes ou des services, la rotation des proxies permet de répartir la charge et d'éviter les blocages par IP. Cela est particulièrement pertinent lors de la surveillance des prix, de la collecte de données ou des tests de disponibilité des ressources depuis différentes régions.
Pour de telles tâches, les proxies de centres de données sont bien adaptés — ils offrent une grande vitesse et stabilité lors de requêtes massives.
#!/bin/bash # rotate_proxy.sh — rotation des proxies à partir d'une liste PROXY_LIST=( "http://user:[email protected]:3128" "http://user:[email protected]:3128" "http://user:[email protected]:3128" "http://user:[email protected]:3128" ) URLS_FILE="urls.txt" OUTPUT_DIR="./results" mkdir -p "${OUTPUT_DIR}" PROXY_COUNT=${#PROXY_LIST[@]} INDEX=0 while IFS= read -r url; do PROXY="${PROXY_LIST[$INDEX]}" FILENAME=$(echo "${url}" | md5sum | cut -d' ' -f1) echo "Demande : ${url} via le proxy $((INDEX + 1))/${PROXY_COUNT}" curl -x "${PROXY}" \ --max-time 30 \ --retry 3 \ --retry-delay 2 \ --silent \ --output "${OUTPUT_DIR}/${FILENAME}.html" \ "${url}" if [ $? -eq 0 ]; then echo " ✓ Succès" else echo " ✗ Échec, tentative avec le prochain proxy..." INDEX=$(( (INDEX + 1) % PROXY_COUNT )) curl -x "${PROXY_LIST[$INDEX]}" \ --max-time 30 \ --silent \ --output "${OUTPUT_DIR}/${FILENAME}.html" \ "${url}" fi # Passer au proxy suivant INDEX=$(( (INDEX + 1) % PROXY_COUNT )) # Petite pause entre les requêtes sleep 0.5 done < "${URLS_FILE}" echo "Terminé ! Résultats sauvegardés dans ${OUTPUT_DIR}"
Une variante plus avancée — vérifier la disponibilité du proxy avant utilisation :
#!/bin/bash # check_proxy.sh — vérification de la disponibilité du proxy check_proxy() { local proxy_url="$1" local test_url="https://api.ipify.org" result=$(curl -x "${proxy_url}" \ --max-time 10 \ --silent \ --write-out "%{http_code}" \ --output /dev/null \ "${test_url}") if [ "${result}" -eq 200 ]; then echo "VIVANT" else echo "MORT" fi } # Obtenir l'IP externe via le proxy get_proxy_ip() { local proxy_url="$1" curl -x "${proxy_url}" --max-time 10 --silent https://api.ipify.org } PROXY="http://user:[email protected]:3128" STATUS=$(check_proxy "${PROXY}") echo "Statut du proxy : ${STATUS}" if [ "${STATUS}" == "VIVANT" ]; then EXTERNAL_IP=$(get_proxy_ip "${PROXY}") echo "IP externe via le proxy : ${EXTERNAL_IP}" fi
10. Débogage et erreurs courantes
Travailler avec des proxies s'accompagne inévitablement d'erreurs — surtout lors de la configuration initiale. Examinons les problèmes les plus courants et les moyens de les diagnostiquer.
Diagnostic avec le mode verbose
# Sortie la plus détaillée de curl curl -vvv -x http://proxy.example.com:3128 https://api.example.com/data 2>&1 | head -50 # Ce qu'il faut surveiller dans la sortie : # * Connecté à proxy.example.com — connexion au proxy établie # CONNECT api.example.com:443 — demande de tunnel # HTTP/1.1 200 Connection established — tunnel ouvert # * SSL connection using TLS — TLS fonctionne # Débogage wget wget -d -e use_proxy=yes -e http_proxy=http://proxy.example.com:3128 https://api.example.com/data
Erreurs courantes et solutions
| Erreur | Cause | Solution |
|---|---|---|
407 Proxy Authentication Required |
Informations d'identification non fournies | Ajouter user:pass dans l'URL du proxy ou flag --proxy-user |
Connection refused |
Port incorrect ou proxy inaccessible | Vérifier le port : nc -zv proxy.host 3128 |
SSL certificate error |
Proxy d'entreprise avec inspection SSL | Ajouter le CA d'entreprise : --cacert /path/to/ca.crt |
Could not resolve proxy |
DNS ne résout pas le nom du proxy | Utiliser l'IP à la place du nom ou vérifier DNS |
Timeout |
Proxy lent ou surchargé | Augmenter le délai d'attente : --max-time 60 |