آیا خط لوله شما با خطای 403 Forbidden یا Connection refused هنگام تلاش برای دسترسی به API خارجی یا دانلود وابستگی مواجه میشود؟ احتمالاً مشکل این است که آدرس IP سرور CI/CD شما در سمت منبع مسدود شده است. پروکسی این مشکل را حل میکند: شما ترافیک را از طریق IP مورد نظر مسیریابی میکنید و خط لوله بدون مشکل کار میکند. در این مقاله — دستورالعملهای مرحله به مرحله برای GitHub Actions، GitLab CI و Jenkins.
چرا پروکسی در CI/CD: سناریوهای واقعی
خطوط لوله CI/CD بر روی سرورهایی با آدرسهای IP ثابت — رنرهای ابری GitHub، GitLab یا بر روی عوامل Jenkins خودتان کار میکنند. این IPها به خوبی شناخته شدهاند و بسیاری از خدمات خارجی یا آنها را مسدود میکنند یا تعداد درخواستها را محدود میکنند. در اینجا سناریوهای خاصی وجود دارد که بدون پروکسی نمیتوان از آنها عبور کرد:
دسترسی به منابع جغرافیایی محدود
بسیاری از ثبتنامهای npm شرکتی، مخازن Maven و APIهای داخلی تنها از کشورهای خاص یا دامنههای IP قابل دسترسی هستند. اگر رنر GitHub Actions شما در منطقهای باشد که در سطح firewall سرویس هدف مسدود شده است، خط لوله نمیتواند وابستگیها را دانلود کند یا دادهها را ارسال کند. پروکسی با موقعیت جغرافیایی مناسب این مشکل را بدون تغییر زیرساخت حل میکند.
محدودیت نرخ و مسدودیتهای IP
رنرهای ابری GitHub Actions از IPهای موجود در دامنههای Microsoft Azure استفاده میکنند. بسیاری از APIهای عمومی این دامنهها را میشناسند و محدودیتهای سختی را بر روی آنها اعمال میکنند — یا به طور کامل مسدود میشوند. به عنوان مثال، تجزیه دادههای عمومی، درخواستها به APIهای خارجی در حین تست، دانلود توزیعها از CDNهای محدود — همه اینها به طور منظم به دلیل IPهای رنرهای ابری خراب میشوند. چرخش از طریق پروکسی اجازه میدهد تا از محدودیت نرخ عبور کنیم.
تست یکپارچهسازی با وبسایتهای واقعی
اگر تستهای یکپارچهسازی شما به وبسایتهای واقعی یا بازارها (Wildberries، Ozon، Avito، Amazon) مراجعه میکنند، این وبسایتها هر بار که اجرا میشوند، یک IP مشابه از رنر را مشاهده میکنند و به سرعت آن را مسدود میکنند. پروکسی با چرخش IP اجازه میدهد تا تستها به طور پایدار بدون CAPTCHA و مسدودیتها انجام شوند.
دسترسی به منابع داخلی شرکتی
شبکههای شرکتی اغلب از دنیای خارجی بسته هستند. اگر خط لوله باید بر روی سرور داخلی مستقر شود یا به API بسته مراجعه کند، پروکسی (یا تونل SOCKS5) درون شبکه شرکتی به عنوان پلی بین رنر ابری و زیرساخت بسته عمل میکند.
تست ادغام تبلیغاتی و بازاریابی
تیمهایی که با API تبلیغات Facebook، API تبلیغات TikTok یا API تبلیغات Google کار میکنند، اغلب ایجاد کمپینها را از طریق CI/CD خودکار میکنند. این پلتفرمها قوانین سختی در مورد IP دارند: درخواستها از IPهای مراکز داده ممکن است مسدود شوند یا نیاز به تأیید اضافی داشته باشند. پروکسیهای مقیم در خط لوله درخواستها را شبیه به ترافیک کاربر عادی میکنند.
کدام نوع پروکسی برای خط لوله انتخاب کنیم
انتخاب نوع پروکسی بستگی به وظیفه دارد. برای خطوط لوله CI/CD سه گزینه مرتبط وجود دارد — هر کدام مزایا و محدودیتهای خود را دارند:
| نوع پروکسی | سرعت | اعتماد سایتها | بهترین برای |
|---|---|---|---|
| پروکسیهای دیتاسنتر | بسیار بالا | متوسط | دانلود وابستگیها، مخازن داخلی، APIهای سریع بدون بررسیهای سخت |
| پروکسیهای مقیم | متوسط | بالا | تستهای یکپارچهسازی با وبسایتهای واقعی، APIهای تبلیغاتی (Facebook، TikTok)، بازارها |
| پروکسیهای موبایل | متوسط | حداکثر | تستهای API موبایل، کار با پلتفرمهایی با حداکثر حفاظتهای ضد ربات |
قاعده عملی:
اگر وظیفه دانلود بستهها یا دسترسی به سرویس داخلی است، از پروکسیهای دیتاسنتر استفاده کنید — آنها سریع و ارزانتر هستند. اگر وظیفه تست در وبسایتهای واقعی یا کار با پلتفرمهای تبلیغاتی است — به پروکسیهای مقیم نیاز دارید. پروتکل SOCKS5 نسبت به HTTP/HTTPS ترجیح داده میشود، زیرا با پورتها و پروتکلهای غیر استاندارد بهتر کار میکند.
تنظیم پروکسی در GitHub Actions
GitHub Actions — محبوبترین ابزار CI/CD در حال حاضر است. تنظیم پروکسی در اینجا از طریق متغیرهای محیطی و رازهای مخزن انجام میشود. بیایید مرحله به مرحله بررسی کنیم.
مرحله 1: افزودن اطلاعات پروکسی به رازهای مخزن
هرگز نام کاربری و رمز عبور پروکسی را مستقیماً در فایل YAML workflow وارد نکنید. از رازهای GitHub استفاده کنید:
- مخزن را باز کنید → تنظیمات → رازها و متغیرها → عملیات
- روی راز جدید مخزن کلیک کنید
- راز
PROXY_URLرا با مقداری به شکلhttp://user:[email protected]:portایجاد کنید
مرحله 2: استفاده از متغیرهای محیطی در workflow
اکثر ابزارها (curl، wget، npm، pip، Maven) به طور خودکار متغیرهای محیطی استاندارد HTTP_PROXY، HTTPS_PROXY و NO_PROXY را شناسایی میکنند. مثال workflow:
name: Build with Proxy
on: [push]
env:
HTTP_PROXY: ${{ secrets.PROXY_URL }}
HTTPS_PROXY: ${{ secrets.PROXY_URL }}
NO_PROXY: localhost,127.0.0.1,internal.company.com
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run integration tests
run: npm test
- name: Call external API
run: |
curl -v https://api.example.com/data
مرحله 3: پروکسی SOCKS5 در GitHub Actions
اگر از SOCKS5 استفاده میکنید (که برای اکثر وظایف توصیه میشود)، متغیرهای محیطی استاندارد کافی نیستند — به یک تونل محلی نیاز دارید. از ابزار proxychains استفاده کنید یا microsocks را تنظیم کنید:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Setup SOCKS5 proxy tunnel
run: |
sudo apt-get install -y proxychains4
echo "socks5 proxy.host 1080 user password" >> /etc/proxychains4.conf
- name: Run command through SOCKS5
run: proxychains4 curl https://restricted-resource.com/api
تنظیم پروکسی برای ابزارهای خاص
برخی ابزارها متغیرهای سیستمی را نادیده میگیرند و نیاز به تنظیم جداگانه دارند:
| ابزار | چگونه پروکسی را تنظیم کنیم |
|---|---|
| npm / yarn | npm config set proxy http://user:pass@host:port |
| pip (Python) | pip install --proxy http://user:pass@host:port package |
| Maven | از طریق settings.xml بخش <proxies> |
| Gradle | systemProp.https.proxyHost=host در gradle.properties |
| Git | git config --global http.proxy http://user:pass@host:port |
| Docker build | --build-arg HTTP_PROXY=http://user:pass@host:port |
تنظیم پروکسی در GitLab CI
GitLab CI چندین سطح برای تعیین متغیرهای محیطی ارائه میدهد: در سطح پروژه، گروه یا نمونه. این امر مدیریت پروکسی را نسبت به GitHub Actions انعطافپذیرتر میکند.
مرحله 1: افزودن متغیرها به GitLab CI/CD Variables
- پروژه را باز کنید → تنظیمات → CI/CD → بخش متغیرها
- روی افزودن متغیر کلیک کنید
- متغیر
PROXY_URLرا با نوع Masked (مقدار را در لاگها پنهان میکند) اضافه کنید - مقدار:
http://user:[email protected]:port
مرحله 2: استفاده از متغیرها در .gitlab-ci.yml
variables:
HTTP_PROXY: $PROXY_URL
HTTPS_PROXY: $PROXY_URL
NO_PROXY: "localhost,127.0.0.1,.internal.company.com"
stages:
- build
- test
- deploy
build:
stage: build
image: node:20-alpine
script:
- npm ci
- npm run build
integration_tests:
stage: test
image: python:3.11
script:
- pip install -r requirements.txt
- pytest tests/integration/
deploy:
stage: deploy
script:
- curl -X POST https://api.external-service.com/deploy
-H "Authorization: Bearer $DEPLOY_TOKEN"
-d '{"version": "$CI_COMMIT_SHA"}'
پروکسی فقط برای شغلهای خاص
اگر پروکسی در همه جا نیاز نیست (به عنوان مثال، فقط برای تستهای یکپارچهسازی، اما نه برای ساخت)، متغیرها را در سطح شغل خاص تعیین کنید، نه به صورت جهانی:
integration_tests:
stage: test
variables:
HTTP_PROXY: $PROXY_URL
HTTPS_PROXY: $PROXY_URL
script:
- pytest tests/integration/
build:
stage: build
# در اینجا پروکسی تعیین نشده است — اتصال مستقیم
script:
- npm ci && npm run build
GitLab Runner خود میزبان: تنظیم پروکسی در سطح رنر
اگر از GitLab Runner خود استفاده میکنید، میتوانید پروکسی را به صورت جهانی در پیکربندی رنر تعیین کنید. فایل /etc/gitlab-runner/config.toml را باز کنید و به بخش [runners.env] اضافه کنید:
[[runners]]
name = "my-runner"
url = "https://gitlab.com/"
token = "TOKEN"
executor = "docker"
environment = [
"HTTP_PROXY=http://user:[email protected]:port",
"HTTPS_PROXY=http://user:[email protected]:port",
"NO_PROXY=localhost,127.0.0.1"
]
این کار راحت است زمانی که همه خطوط لوله در این رنر باید از پروکسی استفاده کنند — نیازی به نوشتن آن در هر .gitlab-ci.yml نیست.
تنظیم پروکسی در Jenkins
Jenkins از سه ابزار دیگر انعطافپذیرتر است، اما تنظیم آن نیز پیچیدهتر است. پروکسی را میتوان در چندین سطح تنظیم کرد: به طور جهانی برای کل Jenkins، برای یک Pipeline خاص یا برای یک مرحله خاص.
روش 1: تنظیمات جهانی پروکسی در Jenkins
- به مدیریت Jenkins → سیستم بروید
- بخش پیکربندی پروکسی HTTP را پیدا کنید
- فیلدها را پر کنید: سرور، پورت، نام کاربری، رمز عبور
- در فیلد No Proxy Host آدرسهای داخلی را با کاما مشخص کنید
- روی آزمایش URL کلیک کنید تا بررسی کنید و ذخیره کنید
این تنظیم بر بارگذاری پلاگینها و بهروزرسانیهای خود Jenkins تأثیر میگذارد، اما به طور خودکار به محیط اجرای خطوط لوله منتقل نمیشود. برای خطوط لوله به پیکربندی جداگانه نیاز است.
روش 2: پروکسی در Pipeline اعلامی از طریق محیط
pipeline {
agent any
environment {
HTTP_PROXY = credentials('proxy-url-credential')
HTTPS_PROXY = credentials('proxy-url-credential')
NO_PROXY = 'localhost,127.0.0.1,internal.company.com'
}
stages {
stage('Build') {
steps {
sh 'npm ci'
sh 'npm run build'
}
}
stage('Integration Tests') {
steps {
sh 'pytest tests/integration/'
}
}
stage('Deploy') {
steps {
sh '''
curl -X POST https://api.external-service.com/deploy \
-H "Authorization: Bearer ${DEPLOY_TOKEN}" \
-d "version=${GIT_COMMIT}"
'''
}
}
}
}
مرحله 3: افزودن اطلاعات حساب پروکسی به اعتبارنامههای Jenkins
- به مدیریت Jenkins → اعتبارنامهها → سیستم → اعتبارنامههای جهانی بروید
- روی افزودن اعتبارنامهها کلیک کنید
- نوع: متن مخفی
- ID:
proxy-url-credential - مخفی:
http://user:[email protected]:port
روش 3: پروکسی از طریق پارامترهای JVM برای پروژههای Java
اگر خط لوله شما پروژه Java (Maven، Gradle) را میسازد، متغیرهای محیطی سیستمی ممکن است کار نکنند — JVM از خواص سیستمی خود استفاده میکند. آنها را به JAVA_OPTS اضافه کنید:
environment {
JAVA_OPTS = '-Dhttps.proxyHost=proxy.host -Dhttps.proxyPort=8080 -Dhttps.proxyUser=user -Dhttps.proxyPassword=password -Dhttp.nonProxyHosts=localhost|127.0.0.1|*.internal.com'
}
پروکسی درون کانتینرهای Docker در خط لوله
اکثر خطوط لوله CI/CD مدرن مراحل را درون کانتینرهای Docker اجرا میکنند. انتقال پروکسی به کانتینر — یک وظیفه جداگانه است که به چندین روش حل میشود.
انتقال پروکسی از طریق --build-arg هنگام ساخت تصویر
اگر پروکسی فقط در حین ساخت تصویر Docker نیاز باشد (به عنوان مثال، برای نصب بستهها درون Dockerfile)، از آرگومانهای ساخت استفاده کنید:
# در .github/workflows/build.yml یا .gitlab-ci.yml
docker build \
--build-arg HTTP_PROXY=$HTTP_PROXY \
--build-arg HTTPS_PROXY=$HTTPS_PROXY \
--build-arg NO_PROXY=$NO_PROXY \
-t myapp:latest .
# در Dockerfile
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
RUN npm ci
⚠️ مهم: امنیت هنگام ساخت تصاویر
متغیرهایی که از طریق ARG و ENV در Dockerfile تعیین میشوند، در متادادههای تصویر ذخیره میشوند و از طریق docker inspect قابل مشاهده هستند. اگر پروکسی نیاز به احراز هویت دارد، اطمینان حاصل کنید که تصویر آماده شده در یک مخزن عمومی منتشر نمیشود — در غیر این صورت، اطلاعات حساب در دسترس عموم قرار میگیرد.
تنظیم جهانی Docker daemon برای پروکسی
در رنرهای خود میزبان میتوان پروکسی را برای کل Docker daemon تنظیم کرد — در این صورت، همه کانتینرها به طور خودکار پروکسی را بدون تغییر در Dockerfile دریافت میکنند:
# /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://user:[email protected]:port"
Environment="HTTPS_PROXY=http://user:[email protected]:port"
Environment="NO_PROXY=localhost,127.0.0.1,registry.internal.com"
# اعمال تغییرات:
# systemctl daemon-reload
# systemctl restart docker
امنیت: چگونه اطلاعات حساب پروکسی را ذخیره کنیم
اطلاعات حساب پروکسی — همانند کلیدهای API یا رمزهای عبور پایگاه داده، اسرار هستند. نشت آنها به این معنی است که هر کسی میتواند از پروکسی شما به هزینه شما استفاده کند. در اینجا قوانین ذخیرهسازی امن آورده شده است:
چک لیست امنیتی
- ✅ هرگز نام کاربری/رمز عبور پروکسی را مستقیماً در فایلهای YAML خط لوله وارد نکنید
- ✅ از متغیرهای مخفی در GitLab و رازهای رمزگذاری شده در GitHub استفاده کنید — آنها در لاگها پنهان میشوند
- ✅ در Jenkins از نوع متن مخفی یا نام کاربری با رمز عبور در فروشگاه اعتبارنامهها استفاده کنید
- ✅
NO_PROXYرا برای آدرسهای داخلی اضافه کنید — ترافیک به زیرساخت خود نباید از طریق پروکسی عبور کند - ✅ به طور منظم رمزهای عبور پروکسی را چرخش دهید — فقط در مخزن اسرار بهروزرسانی کنید، بدون اینکه کد خط لوله را تغییر دهید
- ✅ از احراز هویت IP پروکسی (سفید کردن IP رنر) در جاهایی که پشتیبانی میشود استفاده کنید — این روش مطمئنتر از رمز عبور است
- ✅ لاگهای پروکسی را برای فعالیتهای غیرمعمول بررسی کنید
فرمت URL پروکسی: چه چیزی را کجا قرار دهیم
| پروتکل | فرمت URL | کی استفاده کنیم |
|---|---|---|
| HTTP | http://user:pass@host:port |
اکثر ابزارها، npm، pip، curl |
| HTTPS | https://user:pass@host:port |
اتصال رمزگذاری شده به سرور پروکسی |
| SOCKS5 | socks5://user:pass@host:port |
پورتهای غیر استاندارد، ترافیک UDP، حداکثر سازگاری |
خطاهای رایج و نحوه رفع آنها
حتی پس از تنظیم صحیح ممکن است مشکلاتی پیش بیاید. در اینجا رایجترین خطاها و راهحلهای آنها آورده شده است:
خطا: نیاز به احراز هویت پروکسی (407)
دلیل: نام کاربری یا رمز عبور نادرست است، یا آنها توسط ابزار منتقل نمیشوند.
راهحل: فرمت URL را بررسی کنید — کاراکترهای خاص در رمز عبور باید URL-encode شوند. به عنوان مثال، p@ss#word → p%40ss%23word. همچنین اطمینان حاصل کنید که متغیر محیطی واقعاً به مرحله منتقل میشود — آن را از طریق echo $HTTP_PROXY (حروف اول) برای بررسی چاپ کنید.
خطا: تأیید اعتبار گواهی SSL ناموفق بود
دلیل: پروکسی بازرسی SSL (MITM) را انجام میدهد و گواهی را تغییر میدهد. مشتری به گواهی پروکسی اعتماد ندارد.
راهحل: گواهی ریشه پروکسی را به لیست اعتماد اضافه کنید. برای curl: --cacert /path/to/proxy-ca.crt. برای npm: npm config set cafile /path/to/proxy-ca.crt. یا از پروکسی بدون بازرسی SSL استفاده کنید — این برای CI/CD ترجیح داده میشود.
خطا: زمان اتصال از طریق پروکسی
دلیل: سرور پروکسی از IP رنر در دسترس نیست، یا پورت توسط firewall مسدود شده است.
راهحل: با استفاده از دستور nc -zv proxy.host port در مرحله خط لوله، دسترسی پروکسی را بررسی کنید. اطمینان حاصل کنید که IP رنر به لیست سفید پروکسی ارائهدهنده اضافه شده است (اگر از احراز هویت IP استفاده میشود). برای رنرهای ابری GitHub Actions، دامنههای IP در meta.github.com منتشر میشوند.
خطا: ابزار متغیرهای HTTP_PROXY را نادیده میگیرد
دلیل: برخی ابزارها (به ویژه ابزارهای مبتنی بر Java) متغیرهای محیطی سیستمی را نمیخوانند.
راهحل: از تنظیمات بومی پروکسی برای ابزار خاص استفاده کنید (به جدول بالا مراجعه کنید). برای Java، خواص JVM را از طریق JAVA_OPTS اضافه کنید. برای curl، به طور صریح از پرچم -x http://proxy:port استفاده کنید.
خطا: خدمات داخلی نیز از طریق پروکسی عبور میکنند
دلیل: متغیر NO_PROXY تعیین نشده یا به درستی تعیین نشده است.
راهحل: همه دامنهها و IPهای داخلی را در NO_PROXY مشخص کنید. از wildcard برای دامنهها استفاده کنید: NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,.internal.company.com. توجه داشته باشید: برخی ابزارها از Notation CIDR پشتیبانی میکنند، در حالی که دیگران فقط دامنههای دقیق را میپذیرند.
نتیجهگیری
تنظیم پروکسی در خط لوله CI/CD یک وظیفه یکباره نیست، بلکه بخشی از معماری صحیح اتوماسیون است. ما سه ابزار اصلی را بررسی کردیم: GitHub Actions (از طریق Secrets و متغیرهای محیطی)، GitLab CI (از طریق Variables با ماسک کردن) و Jenkins (از طریق فروشگاه اعتبارنامهها و Pipeline اعلامی). اصول کلیدی برای همه یکسان است: هرگز اطلاعات حساب را در کد ذخیره نکنید، از NO_PROXY برای آدرسهای داخلی استفاده کنید و نوع پروکسی را بر اساس وظیفه خاص انتخاب کنید.
انتخاب نوع پروکسی صحیح برای ثبات خط لوله حیاتی است. برای دانلود وابستگیها و درخواست به APIهای استاندارد، پروکسیهای سریع دیتاسنتر کافی است. اما اگر خط لوله شما تستهای یکپارچهسازی را در وبسایتهای واقعی انجام میدهد، با پلتفرمهای تبلیغاتی (API تبلیغات Facebook، API تبلیغات TikTok) کار میکند یا به بازارها مراجعه میکند — از پروکسیهای مقیم استفاده کنید: IPهای آنها به عنوان ترافیک کاربر عادی درک میشوند و به ندرت تحت مسدودیتها یا محدودیت نرخ قرار میگیرند.
قاعده اصلی: پروکسی را در یک مرحله جداگانه در ابتدای خط لوله تست کنید — این کار به شما اجازه میدهد تا به سرعت مشکلات را تشخیص دهید و زمان خود را برای جستجوی خطا در انتهای یک ساخت طولانی هدر ندهید. یک مرحله curl -v https://api.ipify.org بلافاصله بعد از تنظیم پروکسی اضافه کنید — این مرحله IPای را که درخواستها از آن ارسال میشوند نشان میدهد و تأیید میکند که پروکسی به درستی کار میکند.