Class: AiRootShield::AdvancedProxyDetector

Inherits:
Object
  • Object
show all
Defined in:
lib/ai_root_shield/advanced_proxy_detector.rb

Overview

Advanced proxy detection for VPN, Tor, custom DNS, and MITM appliances

Constant Summary collapse

TOR_INDICATORS =

Known Tor exit node IP ranges and identifiers

{
  dns_names: [
    "tor-exit", "torservers", "artikel5ev", "privacyfoundation",
    "torproject", "exitnode", "tor-relay"
  ],
  asn_patterns: [
    /tor/i, /privacy/i, /anonymous/i, /vpn/i
  ]
}.freeze
VPN_INDICATORS =

Common VPN provider indicators

{
  dns_patterns: [
    /vpn/i, /proxy/i, /tunnel/i, /shield/i, /secure/i,
    /private/i, /anonymous/i, /hide/i, /mask/i
  ],
  asn_patterns: [
    /vpn/i, /virtual private/i, /proxy/i, /datacenter/i,
    /hosting/i, /cloud/i, /server/i
  ],
  known_providers: [
    "nordvpn", "expressvpn", "surfshark", "cyberghost", "pia",
    "mullvad", "protonvpn", "windscribe", "tunnelbear", "hotspotshield"
  ]
}.freeze
MITM_INDICATORS =

MITM appliance indicators

{
  certificate_issuers: [
    /blue coat/i, /websense/i, /forcepoint/i, /zscaler/i,
    /checkpoint/i, /palo alto/i, /fortinet/i, /sophos/i,
    /mcafee/i, /symantec/i, /broadcom/i
  ],
  proxy_headers: [
    "x-bluecoat-via", "x-forwarded-for", "x-real-ip",
    "x-proxy-id", "x-cache", "via", "x-forwarded-proto"
  ]
}.freeze
CUSTOM_DNS_INDICATORS =

Custom DNS server indicators

{
  public_dns: [
    "8.8.8.8", "8.8.4.4",           # Google
    "1.1.1.1", "1.0.0.1",           # Cloudflare
    "208.67.222.222", "208.67.220.220", # OpenDNS
    "9.9.9.9", "149.112.112.112"    # Quad9
  ],
  privacy_dns: [
    "94.140.14.14", "94.140.15.15", # AdGuard
    "76.76.19.19", "76.223.100.101", # Alternate DNS
    "185.228.168.9", "185.228.169.9" # CleanBrowsing
  ]
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(config = {}) ⇒ AdvancedProxyDetector

Returns a new instance of AdvancedProxyDetector.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 65

def initialize(config = {})
  @config = {
    enable_tor_detection: true,
    enable_vpn_detection: true,
    enable_mitm_detection: true,
    enable_dns_detection: true,
    timeout: 5,
    max_retries: 2,
    use_external_apis: false
  }.merge(config)
  
  @detection_cache = {}
  @last_detection_time = {}
end

Instance Method Details

#clear_cache ⇒ Object

Clear detection cache



297
298
299
300
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 297

def clear_cache
  @detection_cache.clear
  @last_detection_time.clear
end

#detect_custom_dns(additional_data, results) ⇒ Hash

Detect custom DNS configuration

Parameters:

  • additional_data (Hash) —

    Additional network data

  • results (Hash) —

    Current results hash

Returns:

  • (Hash) —

    Updated results



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 247

def detect_custom_dns(additional_data, results)
  dns_indicators = []
  
  # Check configured DNS servers
  if additional_data[:dns_servers]
    dns_servers = Array(additional_data[:dns_servers])
    
    dns_servers.each do |dns_server|
      # Check for public DNS services
      if CUSTOM_DNS_INDICATORS[:public_dns].include?(dns_server)
        dns_indicators << "public_dns_detected: #{dns_server}"
      elsif CUSTOM_DNS_INDICATORS[:privacy_dns].include?(dns_server)
        dns_indicators << "privacy_dns_detected: #{dns_server}"
      elsif !is_isp_dns?(dns_server)
        dns_indicators << "custom_dns_detected: #{dns_server}"
      end
    end
  end
  
  # Check for DNS over HTTPS/TLS usage
  if additional_data[:doh_enabled] || additional_data[:dot_enabled]
    dns_indicators << "encrypted_dns_detected"
  end
  
  unless dns_indicators.empty?
    results[:proxy_types] << "custom_dns"
    results[:indicators].concat(dns_indicators)
    results[:details][:dns] = {
      detected: true,
      indicators: dns_indicators,
      risk_level: "low"
    }
  end
  
  results
end

#detect_mitm_appliance(ip, additional_data, results) ⇒ Hash

Detect MITM appliances

Parameters:

  • ip (String) —

    IP address to check

  • additional_data (Hash) —

    Additional network data

  • results (Hash) —

    Current results hash

Returns:

  • (Hash) —

    Updated results



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 203

def detect_mitm_appliance(ip, additional_data, results)
  mitm_indicators = []
  
  # Check for MITM certificate issuers
  if additional_data[:certificates]
    additional_data[:certificates].each do |cert_info|
      issuer = cert_info[:issuer] || ""
      MITM_INDICATORS[:certificate_issuers].each do |pattern|
        if issuer.match?(pattern)
          mitm_indicators << "mitm_certificate_issuer: #{pattern}"
        end
      end
    end
  end
  
  # Check for proxy headers
  if additional_data[:http_headers]
    MITM_INDICATORS[:proxy_headers].each do |header|
      if additional_data[:http_headers].key?(header.downcase)
        mitm_indicators << "proxy_header_detected: #{header}"
      end
    end
  end
  
  # Check for transparent proxy characteristics
  mitm_indicators.concat(detect_transparent_proxy(ip, additional_data))
  
  unless mitm_indicators.empty?
    results[:proxy_types] << "mitm_appliance"
    results[:indicators].concat(mitm_indicators)
    results[:details][:mitm] = {
      detected: true,
      indicators: mitm_indicators,
      risk_level: "high"
    }
  end
  
  results
end

#detect_proxy(target_ip, additional_data = {}) ⇒ Hash

Perform comprehensive proxy detection

Parameters:

  • target_ip (String) —

    IP address to analyze

  • additional_data (Hash) (defaults to: {}) —

    Additional network data

Returns:

  • (Hash) —

    Detection results



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 84

def detect_proxy(target_ip, additional_data = {})
  return cached_result(target_ip) if cached_and_fresh?(target_ip)
  
  results = {
    ip_address: target_ip,
    timestamp: Time.now.to_f,
    proxy_detected: false,
    proxy_types: [],
    confidence_score: 0.0,
    indicators: [],
    details: {}
  }
  
  # Perform different detection methods
  results = detect_tor_exit_node(target_ip, results) if @config[:enable_tor_detection]
  results = detect_vpn_service(target_ip, results) if @config[:enable_vpn_detection]
  results = detect_mitm_appliance(target_ip, additional_data, results) if @config[:enable_mitm_detection]
  results = detect_custom_dns(additional_data, results) if @config[:enable_dns_detection]
  
  # Calculate overall confidence
  results[:confidence_score] = calculate_confidence_score(results)
  results[:proxy_detected] = results[:confidence_score] > 0.5
  
  # Cache results
  cache_result(target_ip, results)
  
  results
end

#detect_tor_exit_node(ip, results) ⇒ Hash

Detect Tor exit nodes

Parameters:

  • ip (String) —

    IP address to check

  • results (Hash) —

    Current results hash

Returns:

  • (Hash) —

    Updated results



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 117

def detect_tor_exit_node(ip, results)
  tor_indicators = []
  
  # Check reverse DNS for Tor indicators
  begin
    hostname = Resolv.getname(ip)
    TOR_INDICATORS[:dns_names].each do |indicator|
      if hostname.downcase.include?(indicator)
        tor_indicators << "tor_dns_pattern: #{indicator}"
      end
    end
  rescue Resolv::ResolvError
    # No reverse DNS available
  end
  
  # Check if IP is in known Tor exit node lists (if external APIs enabled)
  if @config[:use_external_apis]
    tor_indicators.concat(check_tor_exit_lists(ip))
  end
  
  # Check for Tor-specific network characteristics
  tor_indicators.concat(analyze_tor_network_characteristics(ip))
  
  unless tor_indicators.empty?
    results[:proxy_types] << "tor_exit_node"
    results[:indicators].concat(tor_indicators)
    results[:details][:tor] = {
      detected: true,
      indicators: tor_indicators,
      risk_level: "high"
    }
  end
  
  results
end

#detect_vpn_service(ip, results) ⇒ Hash

Detect VPN services

Parameters:

  • ip (String) —

    IP address to check

  • results (Hash) —

    Current results hash

Returns:

  • (Hash) —

    Updated results



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 157

def detect_vpn_service(ip, results)
  vpn_indicators = []
  
  # Check reverse DNS for VPN patterns
  begin
    hostname = Resolv.getname(ip)
    VPN_INDICATORS[:dns_patterns].each do |pattern|
      if hostname.match?(pattern)
        vpn_indicators << "vpn_dns_pattern: #{pattern}"
      end
    end
    
    # Check for known VPN providers
    VPN_INDICATORS[:known_providers].each do |provider|
      if hostname.downcase.include?(provider)
        vpn_indicators << "known_vpn_provider: #{provider}"
      end
    end
  rescue Resolv::ResolvError
    # No reverse DNS available
  end
  
  # Check ASN information for VPN characteristics
  vpn_indicators.concat(analyze_asn_for_vpn(ip))
  
  # Check for datacenter/hosting characteristics
  vpn_indicators.concat(analyze_hosting_characteristics(ip))
  
  unless vpn_indicators.empty?
    results[:proxy_types] << "vpn_service"
    results[:indicators].concat(vpn_indicators)
    results[:details][:vpn] = {
      detected: true,
      indicators: vpn_indicators,
      risk_level: "medium"
    }
  end
  
  results
end

#detection_statistics ⇒ Hash

Get detection statistics

Returns:

  • (Hash) —

    Detection statistics



286
287
288
289
290
291
292
293
294
# File 'lib/ai_root_shield/advanced_proxy_detector.rb', line 286

def detection_statistics
  {
    total_detections: @detection_cache.size,
    cache_hits: @detection_cache.values.count { |v| v[:cached] },
    detection_types: @detection_cache.values.flat_map { |v| v[:proxy_types] }.tally,
    average_confidence: calculate_average_confidence,
    last_detection: @last_detection_time.values.max
  }
end