Class: Html2rss::RequestService::NetworkGuard

Inherits:
Object
  • Object
show all
Defined in:
lib/html2rss/request_service/network_guard.rb

Overview

Enforces public-network reachability for request targets and remote IPs.

Owns DNS resolution, host denylist, and blocked IP ranges. Callers go through Policy so SSRF/origin rules stay single-homed on the public façade.

Constant Summary collapse

LOCAL_HOSTS =

Hostnames treated as local/private surfaces.

%w[localhost localhost.localdomain metadata.google.internal].to_set.freeze
BLOCKED_IP_RANGES =

IP ranges blocked when private networks are disabled.

[
  IPAddr.new('0.0.0.0/8'),
  IPAddr.new('10.0.0.0/8'),
  IPAddr.new('127.0.0.0/8'),
  IPAddr.new('169.254.0.0/16'),
  IPAddr.new('172.16.0.0/12'),
  IPAddr.new('192.168.0.0/16'),
  IPAddr.new('224.0.0.0/4'),
  IPAddr.new('::/128'),
  IPAddr.new('::1/128'),
  IPAddr.new('fe80::/10'),
  IPAddr.new('fc00::/7'),
  IPAddr.new('ff00::/8')
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(allow_private_networks:, resolver: Socket) ⇒ NetworkGuard

Returns a new instance of NetworkGuard.

Parameters:

  • allow_private_networks (Boolean)

    whether private network targets are allowed

  • resolver (#each_address, #getaddrinfo) (defaults to: Socket)

    DNS resolver used for hostname classification



36
37
38
39
40
# File 'lib/html2rss/request_service/network_guard.rb', line 36

def initialize(allow_private_networks:, resolver: Socket)
  @allow_private_networks = allow_private_networks ? true : false
  @resolver = resolver
  freeze
end

Instance Method Details

#enforce_public_network!(url) ⇒ void

This method returns an undefined value.

Rejects URLs whose host is denylisted or resolves to a blocked address.

Parameters:

Raises:



48
49
50
51
52
53
54
# File 'lib/html2rss/request_service/network_guard.rb', line 48

def enforce_public_network!(url)
  host = url.host
  return if allow_private_networks?
  return unless blocked_host?(host) || resolved_ip_addresses(host).any? { |address| blocked_ip?(address) }

  raise PrivateNetworkDenied, "Private network target denied for #{url}"
end

#validate_remote_ip!(ip:, url:) ⇒ void

This method returns an undefined value.

Validates the resolved remote IP for a completed request.

Parameters:

  • ip (String, nil)

    remote IP address reported by the client

  • url (Html2rss::Url)

    URL associated with the response

Raises:



63
64
65
66
67
68
69
70
71
72
# File 'lib/html2rss/request_service/network_guard.rb', line 63

def validate_remote_ip!(ip:, url:)
  return if allow_private_networks?
  return if ip.nil? || ip.empty?

  parsed_ip = parse_ip(ip)
  raise PrivateNetworkDenied, "Remote IP could not be validated for #{url}" unless parsed_ip
  return unless blocked_ip?(parsed_ip)

  raise PrivateNetworkDenied, "Private network target denied for #{url}"
end