aboutsummaryrefslogtreecommitdiff
path: root/contrib/ExerciseServer.py
blob: a4c1046a1152b8c7064918604c97e9d8f173793e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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
112
113
114
115
116
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
#!/usr/bin/python

import TorControl
import threading
import socket
import struct
import random

SOCKS_PORT=9050
CONTROL_PORT=9051

def runSocks4A(nonce, targetHost, targetPort, targetURL):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("127.0.0.1", SOCKS_PORT))
    socksheader = struct.pack("!BBHL", 4, 0x01, targetPort, 1)
    username = ""
    socksheader = "%s%s\x00%s\x00" %(socksheader, username, nonce)
    s.send(socksheader)
    response = s.recv(8)
    version,status,port=struct.unpack("!BBH",response[:4])
    if status != 90:
        print "Error: non-successful SOCKS status"
        s.close()
        return 0

    s.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n"%(targetURL,targetHost))
    while 1:
        r = s.recv(1024)
        if not r:
            print "WOOT! Got a web page."
            s.close()
            return 1

HOSTS_TO_TEST = [ "serifos", "chaoscomputerclub", "NetWorkXXIII", "caethaver2",
                  "theoryorg", "samaire", "alrua", "ihopethisisunique",
                  "xolotl", "cacophony", "ghettocluster", "torserverzillion",
                  "ned", "richhomednsorg", "subzeronet"]
EXITS_TO_TEST = [ "pvt", ]

HOSTS_THAT_WORK = [ "serifos", "rodos", "moria2", "chaoscomputerclub"]
EXITS_THAT_WORK = [ "serifos", "rodos"]

TARGETS = [ ("belegost.mit.edu", "/"),
            ("seul.org", "/")]

N_CIRCS_TO_TRY = 5*len(HOSTS_TO_TEST)
CIRCS_AT_A_TIME = 3
CIRC_LEN = 3

HOST_STATUS = {}
N_CIRCS_DONE = 0
def launchCirc(s):
    htw = HOSTS_THAT_WORK[:]
    random.shuffle(htw)
    path = htw[:CIRC_LEN-2] + \
           [random.choice(HOSTS_TO_TEST)] + \
           [random.choice(EXITS_THAT_WORK)]
    circid = TorControl.extend_circuit(s, 0, path)

    for name in path:
        lst = HOST_STATUS.setdefault(name,[0,0])
        lst[0] += 1
    return circid, path

def runControl(s):
    circs = {}
    s1,s2 = {},{}
    _h = lambda body,circs=circs,s1=s1,s2=s2,s=s:handleEvent(s,body,
                                                             circs,s1,s2)
    TorControl._event_handler = _h
    TorControl.set_events(s,
                          [TorControl.EVENT_TYPE.CIRCSTATUS,
                           TorControl.EVENT_TYPE.STREAMSTATUS])
    TorControl.set_option(s,"__LeaveStreamsUnattached 1")
    global N_CIRCS_DONE
    while N_CIRCS_DONE < N_CIRCS_TO_TRY:
        while len(circs) < CIRCS_AT_A_TIME:
            c,p = launchCirc(s)
            print "launching circuit %s to %s"%(c,p)
            circs[c]=p
        _, tp, body = TorControl.receive_message(s)
        if tp == TorControl.MSG_TYPE.EVENT:
            handleEvent(s, body, circs, s1,s2)
    i = HOST_STATUS.items()
    i.sort()
    for n,(all,good) in i:
        print "%s in %s circuits; %s/%s ok"%(n,all,good,all)

def handleEvent(s, body, circs, streamsByNonce, streamsByIdent):
    global N_CIRCS_DONE
    event, args = TorControl.unpack_event(body)
    if event == TorControl.EVENT_TYPE.STREAMSTATUS:
        status, ident, target = args
        print "Got stream event:",TorControl.STREAM_STATUS.nameOf[status],\
              ident,target
        if status in (TorControl.STREAM_STATUS.NEW_CONNECT,
                      TorControl.STREAM_STATUS.NEW_RESOLVE,
                      TorControl.STREAM_STATUS.DETACHED):
            target,port=target.split(":")
            if not target.endswith(".exnonce"):
                TorControl.attach_stream(s, ident, 0)
            else:
                circid, (host,url) = streamsByNonce[target]
                streamsByIdent[ident] = circid,(host,url)
                print "Redirecting circuit",circid,"to",host
                TorControl.redirect_stream(s, ident, host)
                TorControl.attach_stream(s, ident, circid)
        elif status in (TorControl.STREAM_STATUS.CLOSED,
                        TorControl.STREAM_STATUS.FAILED):
            circid, (host,url) = streamsByIdent[ident]
            if circs.has_key(circid):
                for name in circs[circid]:
                    HOST_STATUS[name][1] += 1
                del circs[circid]
                N_CIRCS_DONE += 1
                print N_CIRCS_DONE, "circuit attempts done"
            del streamsByIdent[ident]
    elif event == TorControl.EVENT_TYPE.CIRCSTATUS:
        status, ident, path = args
        print "Got circuit event",TorControl.CIRC_STATUS.nameOf[status],\
              ident,path
        if status in (TorControl.CIRC_STATUS.CLOSED,
                      TorControl.CIRC_STATUS.FAILED):
            if circs.has_key(ident):
                print "Circuit failed."
                del circs[ident]
                N_CIRCS_DONE += 1
                print N_CIRCS_DONE, "circuit attempts done"
        elif status == TorControl.CIRC_STATUS.BUILT:
            nonce = random.randint(1,100000000)
            nonce = "%s.exnonce" % nonce
            host,url = random.choice(TARGETS)
            streamsByNonce[nonce] = ident, (host,url)
            print "Launching socks4a connection"
            t = threading.Thread(target=runSocks4A, args=(nonce, host, 80, url))
            t.setDaemon(1)
            t.start()


def run():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(("127.0.0.1", CONTROL_PORT))
    TorControl.authenticate(s)
    runControl(s)

if __name__ == '__main__':
    run()