[or-cvs] r16503: {} Add a prototype for building exit summaries from a descripto (projects/dir-stats/trunk)

weasel at seul.org weasel at seul.org
Mon Aug 11 22:30:03 UTC 2008


Author: weasel
Date: 2008-08-11 18:30:03 -0400 (Mon, 11 Aug 2008)
New Revision: 16503

Added:
   projects/dir-stats/trunk/exit-summary
Log:
Add a prototype for building exit summaries from a descriptor

Added: projects/dir-stats/trunk/exit-summary
===================================================================
--- projects/dir-stats/trunk/exit-summary	                        (rev 0)
+++ projects/dir-stats/trunk/exit-summary	2008-08-11 22:30:03 UTC (rev 16503)
@@ -0,0 +1,176 @@
+#!/usr/bin/ruby
+
+# This script builds an exit summary from one server descriptor as proposed in #141.
+# the algorithm doesn't exactly match the proposal - maybe the proposal should be fixed.
+#
+# go over the exit policy lines:
+#   - ignore rejects for netblocks 0.0.0.0/8 169.254.0.0/16 127.0.0.0/8 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12 (exact match, no subnet match (yet))
+#   - ignore accepts unless they are for ip "*"
+#   - for a reject count the number of ips in the netblock against the affected ports
+#   - for an accept to ip "*" add the affected ports to the accepted list if the number of IPs rejected for a port is less than CUTOFF_COUNT
+
+MAX_TCP = 65535
+CUTOFF_COUNT = 2**25
+class Policyitem
+	attr_accessor :from, :to, :rejectcount, :previously_accepted
+	def initialize(from, to, rejectcount = 0, previously_accepted = false)
+		@from = from
+		@to = to
+		@rejectcount = rejectcount
+		@previously_accepted = previously_accepted
+	end
+end
+
+class Policy
+	def initialize
+		@list = []
+		@list << Policyitem.new(1,MAX_TCP)
+
+		@accepted = []
+	end
+	def print_debug
+		puts "START"
+		@list.each do |i|
+			puts " " + (i.from ? i.from.to_s : "nil") + " - " + (i.to ? i.to.to_s : "nil")
+		end
+
+		last_to = 0
+		@list.each do |i|
+			throw "i.from > i.to: #{i.from} > #{i.to}" if i.from > i.to
+			throw "i.from vs. last_to:  #{i.from} > #{last_to}" if i.from != last_to + 1
+			last_to = i.to
+		end
+	end
+	def compress_list(l)
+		index = 0
+		while (l[index+1])
+			if l[index].to+1 == l[index+1].from
+				l[index].to = l[index+1].to
+				l.delete_at(index+1)
+			else
+				index = index+1
+			end
+		end
+		l
+	end
+	def get_accept
+		compress_list(@accepted).collect { |i| (i.from != i.to) ? "#{i.from}-#{i.to}" : i.to.to_s }.join(",")
+	end
+	def get_reject
+		@rejected = []
+		last_accepted = 0
+		@accepted.each do |item|
+			if last_accepted + 1 < item.from
+				@rejected << Policyitem.new(last_accepted + 1, item.from-1)
+			end
+			last_accepted = item.to
+		end
+		if last_accepted < MAX_TCP
+			@rejected << Policyitem.new(last_accepted + 1, MAX_TCP)
+		end
+		compress_list(@rejected).collect { |i| (i.from != i.to) ? "#{i.from}-#{i.to}" : i.to.to_s }.join(",")
+	end
+	def print
+		puts "accept " +get_accept
+		puts "reject " +get_reject
+	end
+	def split(port)
+		port="1-#{MAX_TCP}" if port == "*"
+
+		(from,to) = port.split("-")
+		from = from.to_i
+		to = from unless to
+		to = to.to_i
+
+		index = 0
+		index = index+1 while (@list[index].to < from)
+		if @list[index].from != from
+			@list[index..index] = [ Policyitem.new(@list[index].from, from-1, @list[index].rejectcount, @list[index].previously_accepted),
+			                        Policyitem.new(from, @list[index].to, @list[index].rejectcount, @list[index].previously_accepted)];
+			index = index + 1;
+		end
+		startindex = index
+
+		index = index+1 while (@list[index].to < to)
+		if @list[index].to != to
+			@list[index..index] = [ Policyitem.new(@list[index].from, to, @list[index].rejectcount, @list[index].previously_accepted),
+			                        Policyitem.new(to+1, @list[index].to, @list[index].rejectcount, @list[index].previously_accepted)];
+		end
+		endindex = index
+
+		@list[startindex .. endindex]
+	end
+
+	def add(item)
+		(kind,target) = item.split()
+		(ip,port) = target.split(":")
+		case kind
+			when "reject"
+				return if %w(0.0.0.0/8 169.254.0.0/16 127.0.0.0/8 192.168.0.0/16 10.0.0.0/8 172.16.0.0/12).include? ip
+				reject_some(ip, port)
+			when "accept"
+				if ip == "*" then
+					port_accept(port)
+				end
+			else
+				throw "aaaaaaaaaaaarg"
+		end
+	end
+	def port_accept(port)
+		# we got an accept * to the port(list) in port.
+		matching = split(port)
+		matching.each do |item|
+			next if item.previously_accepted
+			#puts "#{item.from}-#{item.to}: #{item.rejectcount}"
+			next if item.rejectcount >= CUTOFF_COUNT
+			@accepted << item
+			item.previously_accepted = true
+		end
+	end
+	def reject_some(ip, port)
+		# we got a reject ip:port to the port(list) in port.
+		matching = split(port)
+		if ip=="*"
+			count = 2**32
+		else
+			(net,prefixlen) = ip.split("/")
+			prefixlen=32 unless prefixlen
+			count = 2**(32-prefixlen.to_i)
+		end
+
+		matching.each do |item|
+			#puts "Adding #{count} to #{item.from}-#{item.to} from reject #{ip}:#{port}"
+			item.rejectcount = item.rejectcount + count
+		end
+	end
+end
+
+p = Policy.new
+while (line=STDIN.gets) do
+	next unless line =~ /^(reject|accept) /
+	p.add line
+end
+p.print
+
+
+
+# Copyright (c) 2008 Peter Palfrader <peter at palfrader.org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Property changes on: projects/dir-stats/trunk/exit-summary
___________________________________________________________________
Name: svn:executable
   + *



More information about the tor-commits mailing list