summaryrefslogtreecommitdiffstats
path: root/features/support/helpers/firewall_helper.rb
diff options
context:
space:
mode:
Diffstat (limited to 'features/support/helpers/firewall_helper.rb')
-rw-r--r--features/support/helpers/firewall_helper.rb100
1 files changed, 100 insertions, 0 deletions
diff --git a/features/support/helpers/firewall_helper.rb b/features/support/helpers/firewall_helper.rb
new file mode 100644
index 00000000..400965a5
--- /dev/null
+++ b/features/support/helpers/firewall_helper.rb
@@ -0,0 +1,100 @@
+require 'packetfu'
+require 'ipaddr'
+
+# Extent IPAddr with a private/public address space checks
+class IPAddr
+ PrivateIPv4Ranges = [
+ IPAddr.new("10.0.0.0/8"),
+ IPAddr.new("172.16.0.0/12"),
+ IPAddr.new("192.168.0.0/16"),
+ IPAddr.new("255.255.255.255/32")
+ ]
+
+ PrivateIPv6Ranges = [
+ IPAddr.new("fc00::/7"), # private
+ ]
+
+ def private?
+ if self.ipv4?
+ PrivateIPv4Ranges.each do |ipr|
+ return true if ipr.include?(self)
+ end
+ return false
+ else
+ PrivateIPv6Ranges.each do |ipr|
+ return true if ipr.include?(self)
+ end
+ return false
+ end
+ end
+
+ def public?
+ !private?
+ end
+end
+
+class FirewallLeakCheck
+ attr_reader :ipv4_tcp_leaks, :ipv4_nontcp_leaks, :ipv6_leaks, :nonip_leaks
+
+ def initialize(pcap_file, tor_relays)
+ packets = PacketFu::PcapFile.new.file_to_array(:filename => pcap_file)
+ @tor_relays = tor_relays
+ ipv4_tcp_packets = []
+ ipv4_nontcp_packets = []
+ ipv6_packets = []
+ nonip_packets = []
+ packets.each do |p|
+ if PacketFu::TCPPacket.can_parse?(p)
+ ipv4_tcp_packets << PacketFu::TCPPacket.parse(p)
+ elsif PacketFu::IPPacket.can_parse?(p)
+ ipv4_nontcp_packets << PacketFu::IPPacket.parse(p)
+ elsif PacketFu::IPv6Packet.can_parse?(p)
+ ipv6_packets << PacketFu::IPv6Packet.parse(p)
+ elsif PacketFu::Packet.can_parse?(p)
+ nonip_packets << PacketFu::Packet.parse(p)
+ else
+ save_pcap_file
+ raise "Found something in the pcap file that cannot be parsed"
+ end
+ end
+ ipv4_tcp_hosts = get_public_hosts_from_ippackets ipv4_tcp_packets
+ tor_nodes = Set.new(get_all_tor_contacts)
+ @ipv4_tcp_leaks = ipv4_tcp_hosts.select{|host| !tor_nodes.member?(host)}
+ @ipv4_nontcp_leaks = get_public_hosts_from_ippackets ipv4_nontcp_packets
+ @ipv6_leaks = get_public_hosts_from_ippackets ipv6_packets
+ @nonip_leaks = nonip_packets
+ end
+
+ # Returns a list of all unique non-LAN destination IP addresses
+ # found in `packets`.
+ def get_public_hosts_from_ippackets(packets)
+ hosts = []
+ packets.each do |p|
+ candidate = nil
+ if p.kind_of?(PacketFu::IPPacket)
+ candidate = p.ip_daddr
+ elsif p.kind_of?(PacketFu::IPv6Packet)
+ candidate = p.ipv6_header.ipv6_daddr
+ else
+ save_pcap_file
+ raise "Expected an IP{v4,v6} packet, but got something else:\n" +
+ p.peek_format
+ end
+ if candidate != nil and IPAddr.new(candidate).public?
+ hosts << candidate
+ end
+ end
+ hosts.uniq
+ end
+
+ # Returns an array of all Tor relays and authorities, i.e. all
+ # Internet hosts Tails ever should contact.
+ def get_all_tor_contacts
+ @tor_relays + $tor_authorities
+ end
+
+ def empty?
+ @ipv4_tcp_leaks.empty? and @ipv4_nontcp_leaks.empty? and @ipv6_leaks.empty? and @nonip_leaks.empty?
+ end
+
+end