Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 51 additions & 2 deletions src/squid-config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -596,9 +596,10 @@ describe('generateSquidConfig', () => {
};
const result = generateSquidConfig(config);
expect(result).toContain('acl allowed_domains dstdomain');
expect(result).not.toContain('dstdom_regex');
expect(result).toContain('http_access deny !allowed_domains');
// Should not have domain pattern regex (allowed_domains_regex) for plain domains
// Note: IP blocking ACLs (ip_dst_ipv4, ip_dst_ipv6) use dstdom_regex but are separate
expect(result).not.toContain('allowed_domains_regex');
expect(result).toContain('http_access deny !allowed_domains');
});

it('should handle only pattern domains', () => {
Expand Down Expand Up @@ -692,4 +693,52 @@ describe('generateSquidConfig', () => {
expect(result).toContain('# ACL definitions for allowed domain patterns');
});
});

describe('Direct IP Address Blocking (Security)', () => {
it('should include ACL to block direct IPv4 address connections', () => {
const config: SquidConfig = {
domains: ['example.com'],
port: defaultPort,
};
const result = generateSquidConfig(config);
// Should contain IPv4 address blocking ACL
expect(result).toContain('acl ip_dst_ipv4 dstdom_regex');
expect(result).toMatch(/\^\\?\[0-9\]\+/); // Should match IP pattern
});

it('should include ACL to block direct IPv6 address connections', () => {
const config: SquidConfig = {
domains: ['example.com'],
port: defaultPort,
};
const result = generateSquidConfig(config);
// Should contain IPv6 address blocking ACL
expect(result).toContain('acl ip_dst_ipv6 dstdom_regex');
});

it('should deny access to IP addresses before domain filtering', () => {
const config: SquidConfig = {
domains: ['example.com'],
port: defaultPort,
};
const result = generateSquidConfig(config);
// Deny rules should be present and before domain filtering
expect(result).toContain('http_access deny ip_dst_ipv4');
expect(result).toContain('http_access deny ip_dst_ipv6');

// Verify order: IP blocking comes before domain filtering
const ipv4DenyIndex = result.indexOf('http_access deny ip_dst_ipv4');
const domainFilterIndex = result.indexOf('http_access deny !allowed_domains');
expect(ipv4DenyIndex).toBeLessThan(domainFilterIndex);
});

it('should include security comment about bypass prevention', () => {
const config: SquidConfig = {
domains: ['example.com'],
port: defaultPort,
};
const result = generateSquidConfig(config);
expect(result).toContain('bypass prevention');
});
});
});
14 changes: 13 additions & 1 deletion src/squid-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,20 @@ acl Safe_ports port 80
acl Safe_ports port 443
acl CONNECT method CONNECT

# Security: Block direct IP address connections (bypass prevention)
# Clients must use domain names, not raw IP addresses
# This prevents bypassing domain-based filtering via direct IP HTTPS connections
acl ip_dst_ipv4 dstdom_regex ^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$
# IPv6: Must contain at least one colon (distinguishes from domain names)
# Matches: ::1, fe80::1, 2001:db8::1, [::1] (bracket notation for URLs)
acl ip_dst_ipv6 dstdom_regex ^\\[?[0-9a-fA-F]*:[0-9a-fA-F:]*\\]?$

# Access rules
# Deny unsafe ports first
# Deny direct IP connections first (before domain filtering)
http_access deny ip_dst_ipv4
http_access deny ip_dst_ipv6

# Deny unsafe ports
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

Expand Down
Loading