Qwen local development blocked by network policy

Problem – Qwen Local Development Blocked by Network Policy

During local development of Qwen‑based applications, the SDK fails to download model weights or reach the Qwen API. Typical symptoms observed on a developer workstation behind a corporate firewall include:

  • ConnectionError: Failed to establish a new connection: [Errno 111] Connection refused
  • HTTPError 403: Forbidden – https://huggingface.co/.../resolve/main/pytorch_model.bin
  • SSLHandshakeError: certificate verify failed: unable to get local issuer certificate
  • TimeoutError: Request timed out after 30 seconds while contacting https://api.qwen.ai/v1/models
  • ProxyError: Cannot connect to proxy. Check proxy settings and firewall rules.

These errors prevent AutoModel.from_pretrained or API calls such as client.chat(...) from succeeding, halting development cycles.

Root Cause – Network Policy Restrictions

Qwen relies on outbound HTTPS traffic to a well‑known set of domains for:

  • Model weight and tokenizer downloads (e.g., *.huggingface.co, *.modelscope.cn).
  • API endpoint access (api.qwen.ai, api.qwen.cn).
  • Optional CDN mirrors (*.aliyuncs.com).

Corporate firewalls or network security groups often enforce one or more of the following policies:

  1. Outbound port blocking: Only ports 80/443 are permitted, but some environments also restrict TLS SNI, causing SSLHandshakeError (see the real incident where a security appliance stripped SNI).
  2. Domain whitelisting: The firewall permits only a curated list of domains. Missing entries such as modelscope.cn force Qwen’s ModelDownloader to fallback to HTTP, resulting in 403 Forbidden responses.
  3. Proxy enforcement: A mandatory HTTP/HTTPS proxy is required for outbound traffic. If HTTP_PROXY/HTTPS_PROXY are not set, the SDK attempts direct connections and receives Connection refused or TimeoutError.

These constraints align with the Model Hub Access Policy and the Alibaba Cloud Qwen SDK network requirements. When the required domains or ports are not explicitly allowed, Qwen cannot reach its external resources.

Debug – Investigation and Diagnostics

1. Verify Environment Variables

echo $HTTP_PROXY $HTTPS_PROXY

If empty, the SDK will bypass the corporate proxy.

2. Inspect Firewall Logs

2026-06-17 14:23:11 firewall: DENY OUTBOUND tcp src=10.2.5.12 dst=34.230.45.67 dport=443

2026-06-17 14:23:12 firewall: DENY OUTBOUND tcp src=10.2.5.12 dst=52.199.123.45 dport=443

These entries correspond to huggingface.co and modelscope.cn respectively.

3. Capture TLS Handshake with tcpdump

sudo tcpdump -i any -n port 443 -w /tmp/qwen.pcap

Open the capture in Wireshark and check the Server Name Indication (SNI). Missing SNI indicates a middlebox stripping it, which leads to SSLHandshakeError.

4. Use curl with Proxy to Test Reachability

curl -x http://proxy.corp:8080 -I https://huggingface.co/Qwen/Qwen-7B

Expected output:

HTTP/2 200 
content-type: application/json
...

5. Review Qwen SDK Logs

2026-06-17 14:25:03,456 – qwen.downloader – ERROR – Failed to download https://huggingface.co/Qwen/Qwen-7B/resolve/main/pytorch_model.bin: ConnectionError: Failed to establish a new connection: [Errno 111] Connection refused

6. Compare Required Domains vs. Whitelist

Required Domain Current Whitelist
*.huggingface.co
*.modelscope.cn
api.qwen.ai
*.aliyuncs.com

Solution – Configuring Network Access for Qwen

1. Add Required Domains to Firewall Whitelist

Update the outbound rule set to include the following entries (both TCP 80 and 443):

# Example iptables rule on a Linux gateway
iptables -A OUTPUT -p tcp -d .huggingface.co --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp -d .modelscope.cn --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp -d api.qwen.ai --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp -d .aliyuncs.com --dport 443 -j ACCEPT

2. Set Proxy Environment Variables for Development Sessions

Before (missing proxy):

# No proxy variables defined

After (proxy configured):

export HTTP_PROXY="http://proxy.corp:8080"
export HTTPS_PROXY="http://proxy.corp:8080"
export NO_PROXY="localhost,127.0.0.1"

3. Configure Qwen SDK to Use the Proxy Explicitly

If the SDK does not pick up environment variables, pass a Session object:

import os
import requests
from qwen import QwenClient

session = requests.Session()
session.proxies = {
    "http": os.getenv("HTTP_PROXY"),
    "https": os.getenv("HTTPS_PROXY"),
}
client = QwenClient(session=session)

# Verify download works
model = client.AutoModel.from_pretrained("Qwen/Qwen-7B")

4. Enable SNI Preservation on Security Appliance

For appliances that strip SNI, add an exception or upgrade firmware to retain the TLS extension. After the change, a re‑run of the download should succeed without SSLHandshakeError.

5. Optional: Use a Local Mirror

When corporate policy forbids direct internet access, mirror the model files on an internal HTTP server:

# Mirror download (run once on a machine with internet)
git lfs install
git clone https://huggingface.co/Qwen/Qwen-7B /tmp/qwen-mirror
# Serve via internal nginx
server {
    listen 443 ssl;
    server_name models.internal.corp;
    root /tmp/qwen-mirror;
    ...
}
# Update code to point to the mirror
model = AutoModel.from_pretrained("models.internal.corp/Qwen-7B")

Verify – Confirming Successful Access

  1. Run a quick model load test:
python - <<'PY'
from qwen import AutoModel
model = AutoModel.from_pretrained("Qwen/Qwen-7B")
print("Model loaded, vocab size:", len(model.config.vocab))
PY

Expected console output:

Model loaded, vocab size: 50257
  • Check API connectivity:
  • curl -x $HTTPS_PROXY -I https://api.qwen.ai/v1/models
    

    Should return HTTP/2 200.

  • Inspect SDK logs for absence of connection errors:
  • grep -i "ERROR" ~/.qwen/logs/qwen.log
    

    No Qwen‑related error lines should appear.

    Prevent – Best Practices and Ongoing Guardrails

    • Maintain a version‑controlled whitelist: Store allowed domains and ports in a YAML file and audit quarterly.
    • Automate proxy detection: Add a startup script that validates HTTP_PROXY/HTTPS_PROXY against a known test endpoint (e.g., https://huggingface.co/.well-known/openid-configuration).
    • Monitor outbound traffic: Create a Prometheus metric qwen_outbound_success_total and alert on sudden drops.
    • Document fallback mirrors: Keep internal mirror URLs in README.dev.md so new engineers know the preferred source.
    • Validate TLS handshakes: Periodically run a health‑check job that performs an openssl s_client -connect api.qwen.ai:443 -servername api.qwen.ai and verifies the certificate chain.

    FAQ – Common Follow‑Up Questions

    1. Why does the model download succeed on my laptop but fail on the CI runner?
      CI runners often run in isolated networks without the corporate proxy or with stricter outbound rules. Ensure the runner inherits the same HTTP_PROXY/HTTPS_PROXY settings and that the firewall whitelist includes the required domains.
    2. Can I restrict Qwen to a single mirror without touching the firewall?
      Yes. Set the QWEN_MODEL_REPO environment variable (or use the repo_id argument) to point to an internal HTTP/HTTPS server that hosts the model files.
    3. What ports must be opened for Qwen API calls?
      Only TCP 443 (HTTPS) is required for api.qwen.ai and model hub domains. Some legacy endpoints also listen on 80, but they redirect to 443.
    4. My proxy requires authentication. How do I pass credentials?
      Include them in the proxy URL: export HTTPS_PROXY="http://user:password@proxy.corp:8080". For security, store the credentials in a secret manager and inject them at runtime.
    5. After fixing the firewall, I still see SSLHandshakeError. What else could be wrong?
      Check that the security appliance preserves the SNI extension. If not, either update the appliance configuration or use a direct connection (bypass the appliance) for the Qwen domains.

    Related Topic Hub: LLM Systems Troubleshooting Hub