yum-apt 代理服务器搭建
前提:代理服务端统一使用 Ubuntu 20.04(
172.27.248.66/ igo66),Squid 与 apt-cacher-ng 同机部署;客户端分别为 CentOS 7(yum)与 Ubuntu 20/22(apt)。非 root 用户命令前加sudo。
一、Ubuntu 20.04 — yum 代理(Squid)
服务端 172.27.248.66(igo66)
sudo apt update && sudo apt install -y squid && sudo systemctl enable --now squid
sudo tee /etc/squid/squid.conf > /dev/null <<'EOF'
http_port 3128
https_port 3122 tls-cert=/home/igo/ssl/tls.pem tls-key=/home/igo/ssl/tls.key
cache_dir ufs /var/spool/squid 1024 16 256
cache_mem 512 MB
maximum_object_size 4096 MB
cache_replacement_policy heap LFUDA
cache_access_log /var/log/squid/access.log
cache_log /var/log/squid/cache.log
acl localnet src 10.0.0.0/8
acl localnet src 172.16.0.0/12
acl localnet src 192.168.0.0/16
http_access allow localnet
http_access allow all
http_access deny all
forwarded_for off
request_header_access Allow allow all
# 66 出网受限时取消下面两行注释,经 10.80.238.40:3128 二级转发出站
# cache_peer 10.80.238.40 parent 3128 0 no-query default connect-fail-limit=0
# never_direct allow all
EOF
TLS 证书权限(Squid 以 proxy 用户运行,私钥不可全局可读):
sudo chmod 711 /home/igo
sudo chown root:proxy /home/igo/ssl
sudo chmod 750 /home/igo/ssl
sudo chown root:proxy /home/igo/ssl/tls.pem /home/igo/ssl/tls.key
sudo chmod 644 /home/igo/ssl/tls.pem
sudo chmod 640 /home/igo/ssl/tls.key
sudo -u proxy test -r /home/igo/ssl/tls.pem && sudo -u proxy test -r /home/igo/ssl/tls.key \
&& echo "cert/key OK" || echo "cert/key FAIL"
初始化缓存、校验配置、启动并检查状态:
sudo squid -z && sudo squid -k parse && sudo systemctl enable squid \
&& sudo systemctl restart squid
sudo systemctl --no-pager status squid
sudo ufw allow 3128/tcp 2>/dev/null; sudo ufw allow 3122/tcp 2>/dev/null; \
sudo ss -lntp | grep -E '3128|3122'
https_port 3122避开 22 端口(易被网络策略拦截或与 SSH 冲突)。
Squid 就绪后,在客户端配置 HTTP/HTTPS 代理:
P=172.27.248.66; export http_proxy=http://${P}:3128 https_proxy=http://${P}:3128 HTTP_PROXY=http://${P}:3128 HTTPS_PROXY=http://${P}:3128 no_proxy=localhost,127.0.0.0/8,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16; history -d $(history 1 | awk '{print $1}') 2>/dev/null
验证 shell 代理是否生效(自动读取上述环境变量,无需 -x):
bash <<'EOF'
echo "proxy: ${http_proxy:-${HTTP_PROXY:-unset}}"
for u in \
http://www.google.com/ \
https://www.google.com/ \
http://docker.io/ \
https://docker.io/; do
curl -sS -o /dev/null -w "${u} HTTP=%{http_code} time=%{time_total}s\n" \
--connect-timeout 5 --max-time 20 -I "$u" || echo "${u} FAIL"
done
EOF
docker pull 走 dockerd 进程,不读 shell 代理;需单独配置:
P=172.27.248.66
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf > /dev/null <<EOF
[Service]
Environment="HTTP_PROXY=http://${P}:3128"
Environment="HTTPS_PROXY=http://${P}:3128"
Environment="NO_PROXY=localhost,127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
EOF
sudo systemctl daemon-reload && sudo systemctl restart docker
sudo systemctl show docker --property=Environment
history -w; sed -i '/proxy=\|http_proxy\|HTTP_PROXY\|HTTPS_PROXY\|NO_PROXY/d' "${HISTFILE:-$HOME/.bash_history}" 2>/dev/null; history -c; history -r
取消 shell 代理:
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY no_proxy
取消 Docker 代理:
sudo rm -f /etc/systemd/system/docker.service.d/http-proxy.conf
sudo systemctl daemon-reload && sudo systemctl restart docker
CentOS 7 客户端
CentOS 7 已 EOL,官方 mirrorlist.centos.org 常返回 503,需改用阿里云源;yum 流量经 Squid 代理出网。
1. 经代理测试阿里云源是否可达(可选)
在客户端执行,HTTP=200 表示可用:
timeout 20 bash -c 'PROXY=http://172.27.248.66:3128; echo "=== Aliyun Centos-7.repo ==="; timeout 8 curl -x "${PROXY}" -sS -o /dev/null -w "HTTP=%{http_code} time=%{time_total}s\n" --connect-timeout 5 --max-time 8 -I http://mirrors.aliyun.com/repo/Centos-7.repo || echo "FAIL"; echo "=== Aliyun base repomd.xml ==="; timeout 8 curl -x "${PROXY}" -sS -o /dev/null -w "HTTP=%{http_code} time=%{time_total}s\n" --connect-timeout 5 --max-time 8 -I http://mirrors.aliyun.com/centos-vault/7.9.2009/os/x86_64/repodata/repomd.xml || echo "FAIL"'
2. 配置代理 + 阿里云源
旧文件 centos.repo(小写)不会被 CentOS-*.repo 匹配,仍指向 yum.sunwoda-evb.com 并与阿里云源重复;需按文件名 cent* 忽略大小写 全部移走后再下载新 repo。
PROXY=http://172.27.248.66:3128
grep -q '^proxy=' /etc/yum.conf || sudo sed -i "/^\[main\]/a proxy=$PROXY" /etc/yum.conf
sudo mkdir -p /etc/yum.repos.d/backup
for file in /etc/yum.repos.d/[Cc]ent*; do
[ -e "$file" ] || continue
sudo mv "$file" /etc/yum.repos.d/backup/
done
sudo curl -x "$PROXY" -fsSL -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
sudo curl -x "$PROXY" -fsSL -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
sudo yum clean all && sudo yum makecache && sudo yum repolist
history -w; sed -i '/proxy=\|http_proxy\|HTTP_PROXY\|HTTPS_PROXY\|NO_PROXY/d' "${HISTFILE:-$HOME/.bash_history}" 2>/dev/null; history -c; history -r
原
centos.repo若含 nginx/zabbix 等内网源,移走后需单独保留或重建对应.repo;base/epel 仅使用上述阿里云文件即可。
取消代理:
sudo sed -i '/^proxy=/d' /etc/yum.conf && sudo yum clean all
二、Ubuntu 20.04 — apt 代理(apt-cacher-ng)
服务端 172.27.248.66(igo66,与 Squid 同机)
sudo apt update && sudo apt install -y apt-cacher-ng && sudo systemctl enable --now apt-cacher-ng
sudo tee /etc/apt-cacher-ng/acng.conf > /dev/null <<'EOF'
Port:3142
BindAddress:0.0.0.0
CacheDir:/var/cache/apt-cacher-ng
LogDir:/var/log/apt-cacher-ng
ExTreshold:4
EOF
sudo systemctl restart apt-cacher-ng && sudo ufw allow 3142/tcp 2>/dev/null; \
sudo ss -lntp | grep 3142
apt-cacher-ng 按请求 URL 自动区分发行版,同一代理可同时服务 Ubuntu 20.04 / 22.04 客户端。
Ubuntu 20.04 / 22.04 客户端
配置 apt 代理前,确认 apt-cacher-ng 可用:
P=172.27.248.66; PROXY=http://${P}:3142
bash <<EOF
echo "proxy: $PROXY"
for u in \
http://archive.ubuntu.com/ \
https://archive.ubuntu.com/ \
http://security.ubuntu.com/ \
https://security.ubuntu.com/; do
curl -x "$PROXY" -sS -o /dev/null -w "\${u} HTTP=%{http_code} time=%{time_total}s\n" \
--connect-timeout 5 --max-time 20 -I "\$u" || echo "\${u} FAIL"
done
EOF
PROXY=http://172.27.248.66:3142
sudo tee /etc/apt/apt.conf.d/01proxy > /dev/null <<EOF
Acquire::http::Proxy "$PROXY";
Acquire::https::Proxy "$PROXY";
EOF
sudo apt update && sudo apt -s upgrade | head -5
history -w; sed -i '/proxy=\|http_proxy\|HTTP_PROXY\|HTTPS_PROXY\|Acquire::http/d' "${HISTFILE:-$HOME/.bash_history}" 2>/dev/null; history -c; history -r
取消代理:
sudo rm -f /etc/apt/apt.conf.d/01proxy && sudo apt update
三、验证与排错
在客户端执行以下聚合命令(脚本内英文输出;兼容 CentOS 7 / Rocky 9 / Ubuntu 20/22)。
端口 TCP 连通性
仅检测代理端口能否建立 TCP,不验证证书或代理协议。
bash <<'EOF'
P=172.27.248.66
echo "=== Proxy port TCP check (target: $P) ==="
for p in 3128 3122 3142; do
timeout 3 bash -c "echo >/dev/tcp/$P/$p" 2>/dev/null \
&& echo "[OK] $P:$p" || echo "[FAIL] $P:$p"
done
EOF
经代理访问 Google
3128 为 HTTP 代理,可直接用 IP;3122 为 HTTPS 代理,证书按域名签发,需临时写入 hosts。
bash <<'EOF'
P=172.27.248.66; H=igoproxy.sunwoda-evb.com
grep -qw "$H" /etc/hosts || echo "$P $H" | sudo tee -a /etc/hosts > /dev/null
echo "=== Google via HTTP proxy $P:3128 ==="
curl -x http://$P:3128 -sS -o /dev/null \
-w "HTTP=%{http_code} time=%{time_total}s\n" \
--connect-timeout 5 --max-time 20 -I https://www.google.com/ \
|| echo "FAIL"
echo "=== Google via HTTPS proxy $H:3122 (hosts required for TLS cert) ==="
curl --proxy-insecure -x https://$H:3122 -sS -o /dev/null \
-w "HTTP=%{http_code} time=%{time_total}s\n" \
--connect-timeout 5 --max-time 20 -I https://www.google.com/ \
|| curl -k -x https://$H:3122 -sS -o /dev/null \
-w "HTTP=%{http_code} time=%{time_total}s\n" \
--connect-timeout 5 --max-time 20 -I https://www.google.com/ \
|| echo "FAIL"
EOF
测完可清理 hosts:sudo sed -i '/igoproxy\.sunwoda-evb\.com/d' /etc/hosts
单项检查
| 检查项 | 命令 |
|---|---|
| yum 代理连通 | curl -x http://172.27.248.66:3128 -I http://mirrors.aliyun.com/centos-vault/7.9.2009/os/x86_64/repodata/repomd.xml |
| apt 代理连通 | curl -I http://172.27.248.66:3142/acng-report.html |
| Squid 日志 | sudo tail -f /var/log/squid/access.log |
| apt-cacher 日志 | sudo tail -f /var/log/apt-cacher-ng/apt-cacher.log |
常见问题
- 客户端无法访问:服务端
ufw放行 3128 / 3122 / 3142,确认 Squid ACL 网段包含客户端 IP。 - yum
mirrorlist.centos.org503:CentOS 7 已 EOL,改用阿里云源(见第一节客户端步骤),勿再用官方 mirrorlist。 - yum 报 SSL 错误:CentOS 7 阿里云源多为 HTTP,保持
proxy=即可;HTTPS 源需 Squid 额外配置 SSL bump(一般内网镜像无需)。 - apt 慢或 403:确认客户端
/etc/apt/sources.list使用官方或内网可达镜像源,代理只做缓存转发。
四、架构示意
CentOS 7 客户端 ──proxy:3128──► Ubuntu 20.04 172.27.248.66 (Squid) ──► mirrors.aliyun.com
Ubuntu 20/22 客户端 ──proxy:3142──► Ubuntu 20.04 172.27.248.66 (apt-cacher-ng) ──► 上游 apt 镜像
报错
-
yum.sunwoda-evb.com/ repo 重复:检查是否仍有/etc/yum.repos.d/centos.repo(小写)未移走,与CentOS-Base.repo重复定义 base/epel;按客户端步骤用[Cc]ent*全部备份后再makecache。 -
mirrorlist.centos.org503:CentOS 7 已 EOL,改用阿里云源,勿再用官方 mirrorlist。 -
EPEL 404/503(内网源):改用
mirrors.aliyun.com/repo/epel-7.repo;临时装包可sudo yum --disablerepo=epel -y install <pkg>。
sudo yum --disablerepo=epel -y install mlocate htop
sudo yum-config-manager --save --setopt=epel.skip_if_unavailable=true
五、出站 TCP 探测(15 站点)
在待测客户端或服务端执行,探测常用 yum/apt/k8s/docker/GitHub/Helm 等站点 80/443 TCP 是否可达(非 HTTP 内容检测)。每端口超时 3s,并行执行,整段上限 12s;无需 root。
判读: OK 已连通 | refused 主动拒绝 | reset 连接被 RST | unreach 无路由 | timeout 超过 3s 无响应(多为防火墙 DROP)
timeout 12 bash <<'EOF'
cfn(){ e="$1"; c="$2"
[ "$c" -eq 0 ] && echo OK && return
[ "$c" -eq 124 ] && echo timeout && return
e=$(printf '%s' "$e" | tr '\n' ' ' | sed 's/ */ /g;s/^bash: //g')
echo "$e" | grep -qi refused && echo refused && return
echo "$e" | grep -qi reset && echo reset && return
echo "$e" | grep -qi unreachable && echo unreach && return
echo "$e" | grep -qi 'no route' && echo unreach && return
echo "$e" | grep -qi timeout && echo timeout && return
printf 'err(%.28s)' "$e"
}
p(){ l="$1"; h="$2"; o=""
for pt in 80 443; do
e=$(timeout 3 bash -c "echo >/dev/tcp/${h}/${pt}" 2>&1); c=$?
o="${o} ${pt}:$(cfn "$e" "$c")"
done
printf "%-14s %-28s%s\n" "$l" "$h" "$o"
}
echo "=== Egress TCP probe (80+443/host, 3s/port, parallel) ==="
echo "Legend: OK=connected | refused=reject | reset=RST | unreach=no route | timeout=>3s no reply"
echo ""
while IFS='|' read -r l h; do p "$l" "$h" & done <<'T'
Aliyun|mirrors.aliyun.com
Tsinghua|mirrors.tuna.tsinghua.edu.cn
Tencent-yum|mirrors.cloud.tencent.com
Ubuntu-apt|archive.ubuntu.com
Ubuntu-sec|security.ubuntu.com
GitHub|github.com
Google|www.google.com
DockerHub|registry-1.docker.io
Docker-pkg|download.docker.com
K8s|pkgs.k8s.io
Helm|get.helm.sh
Quay|quay.io
Debian|deb.debian.org
GCS|storage.googleapis.com
MS-pkg|packages.microsoft.com
T
wait
echo ""
echo "=== Done ==="
EOF