Fixing merge conflict on gitignore
Fixing merge conflict on gitignore

file:a/.gitignore -> file:b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
+*~
 
-

file:b/README (new)
--- /dev/null
+++ b/README
@@ -1,1 +1,96 @@
+BASH Haystack generator
+==========================
 
+
+About
+--------
+
+BASH Haystack generator is a small set of BASH scripts (server-side and client-side) to generate random data for requesting/sending via Tor/VPN at random intervals to increase the level of irrelevant traffic which may be observed by a monitoring adversary and reduce the effectiveness of recording traffic patterns over encrypted tunnels.
+
+The server-side scripts generate a file of a fixed size (default 1GB) containing random(ish) data from /dev/urandom (by default).
+
+The client scripts request bits of that data (with the option to use a random generator to decide whether to request anything on this run or not). The number of requests made (and the size of the ranges) are also randomly generated (whether per-run or per-request)
+
+The client script currently supports the following
+
+* Downloading of random byte ranges
+* Randomise the number of requests per run
+* Randomise the delay between requests
+* Also send random amounts of data upstream
+* Can be disabled via logfile
+* User-agent can be customised for easy identification in server logs
+
+
+The server side script is much, much simpler. Both are designed to be run by cron (though you may want to redirect the client script's stdout to /dev/null)  
+
+
+
+Requirements
+--------------
+
+The base requirements for the client are
+
+* Curl
+* tr
+* dd
+* fold
+
+The requirements for the server are
+
+* dd
+* Some kind of HTTP(s) server to serve the generated file
+
+Note: It's up to the network administrator to ensure that the relevant traffic is routed over their VPN (or Tor) connection.  
+
+
+
+HTTP Server Specific Notes
+-------------------------------
+
+If the remote server is using NGinx and the client has been configured with SEND_DATA=y then a default install of NGinx will not return the requested data, instead giving a HTTP 405 (Method not allowed).
+
+The fix (unpleasant as it is) is to add the following to the relevant server block
+
+	error_page 405 = $uri;
+
+  
+
+
+
+Notes on Atomicity
+---------------------
+
+The client script was deliberately designed with no atomicity, if one run takes a while then the next may quite possibly start before it's completed. Given that the aim is to render measurements of traffic meaningless this is a good thing as it helps reduce the likelihood of your scheduled traffic run being quite so identifiable.  
+
+
+
+
+Suggested Run Interval
+-------------------------
+
+The most appropriate run interval will differ by each users situation, but common sense should be applied. There's not a huge amount of point in attempting to mask your traffic if the script doing the masking runs once every 12 hours for 5 minutes a time.
+
+There may also be situations where it's better to run the script in a while loop than to add it to crontab.  
+
+
+
+Client - Multiple Config Files
+----------------------------------
+
+Although the default config file is called 'config' you can pass the filename of an alternative config file if you wish to maintain multiple configurations
+
+	./request_generator -c foo.config
+
+The filename passed can either be an absolute path, or the name of a config file in the same directory as the request_generator script.
+
+
+---------------------------------------
+
+
+
+License
+--------
+
+Copyright (C) 2014 B Tasker
+Released under the [GNU GPL V2](http://www.gnu.org/licenses/gpl-2.0.html)
+

--- /dev/null
+++ b/client-side/config
@@ -1,1 +1,28 @@
+#
+# Configuration file for the Client-Side haystack script
+#
+#
 
+
+# To disable the script temporarily, simply create a file at the location below
+LOCKFILE='/tmp/haystackfile.lock'
+
+# Endpoint configuration
+REMOTE_FILE='http://www.example.com/largefile'
+HTTP_HOSTNAME='www.example.co.uk'
+
+
+# Data Downloads
+MAX_CHUNK_SIZE=6553600 # Maximum chunk size to request (bytes, default is 6553600bytes/50MB)
+MAX_REQUESTS=100 # Maximum number of requests to make per session
+RANDOMIZE_CHUNKSIZE="y" # Set this to n if you want to use the same size chunk-size throughout a session
+USER_AGENT='HaystackGen V0.1'
+MAX_DELAY=5 # What should the maximum delay between requests be?
+
+# Data uploads
+SEND_DATA="r" # Should random data also be sent upstream? (values - y/n/r) Setting to r gives a 1/2 chance of it being a y
+MAX_UPSTREAM="655360" # Data will be a stream of chars, so 1 = 1 byte, take your upstream speeds into consideration
+RANDOMIZE_US_CHUNKSIZE="y" # Set this to n to use the same size upstream chunks per session
+
+
+

--- /dev/null
+++ b/client-side/request_generator.sh
@@ -1,1 +1,139 @@
+#!/bin/bash
+#
+# Client side traffic generator
+#
 
+mydir=`dirname $0`
+
+
+# Load the configuration file
+while getopts "c:" flag
+do
+
+        case "$flag" in
+                c) configfile="$OPTARG";;
+        esac
+done
+
+
+configfile=${configfile:-"$mydir/config"}
+
+
+if [[ ! -f "$configfile" ]]
+then
+	if [[ ! -f "$mydir/$configfile" ]]
+	then
+		echo "Config file ($configfile) not found"
+		exit
+	fi
+	configfile="$mydir/$configfile"
+fi
+
+
+# read in the config file
+source "$configfile"
+
+
+# Check whether the lockfile exists and exit if so
+[[ -f "$LOCKFILE" ]] && exit;
+
+
+# Function to place the request - may do more later
+placeRequest(){
+	URL=$1
+	HOST=$2
+	START=$3
+	END=$4
+	UPSTREAM=$5
+	DATA=$6
+
+	if [ "$UPSTREAM" == 'n' ]
+	then
+		# Place the request
+		curl -H "User-agent: $USER_AGENT" -H "Host: $HOST" -H "Range: bytes=$START-$END" "$URL" > /dev/null 2> /dev/null
+	else
+		curl -X POST -d "$DATA" -H "User-agent: $USER_AGENT" -H "Host: $HOST" -H "Range: bytes=$START-$END" "$URL" > /dev/null 2> /dev/null
+	fi
+}
+
+
+
+
+# Start
+
+# We're going to be using RANDOM quite a lot
+RANDOM=$$ # Start by seeding with the pid
+
+REQUESTS=$((RANDOM%$MAX_REQUESTS)) # How many requests to make
+
+if [[ "$RANDOMIZE_CHUNKSIZE" == "n" ]]
+then
+	CHUNKS=$((RANDOM%$MAX_CHUNK_SIZE)) # Chunk size
+fi
+
+
+# Has sending data upstream been set to random
+if [[ "$SEND_DATA" == "r" ]]
+then
+	no=$((RANDOM%2))
+
+	if [[ "$no" == "0" ]]
+	then
+		SEND_DATA="y"
+	else
+		SEND_DATA="n"
+	fi
+
+fi
+
+# If we're to send data upstream, are we supposed to be randomising with each request?
+if [[ "$SEND_DATA" == "y" ]] && [[ "$RANDOMIZE_US_CHUNKSIZE" == "n" ]]
+then
+	UPSTREAM_LEN=$((RANDOM%$MAX_UPSTREAM))
+	UPSTREAM_DATA=`cat /dev/urandom | tr -dc 'a-zA-Z0-9-_@#$%^&*()_+{}|:<>?='|fold -w $UPSTREAM_LEN| head -n 1`
+fi
+
+
+echo "Will place $REQUESTS Request(s)"
+
+for i in `seq 1 $REQUESTS`
+do
+
+	# Calculate the chunksize if needed
+	if [[ ! "$RANDOMIZE_CHUNKSIZE" == "n" ]]
+	then
+		CHUNKS=$((RANDOM%$MAX_CHUNK_SIZE)) # Chunk size
+	fi
+
+	if [[ "$SEND_DATA" == "y" ]] && [[ "$RANDOMIZE_US_CHUNKSIZE" == "y" ]]
+	then
+		UPSTREAM_LEN=$((RANDOM%$MAX_UPSTREAM))
+		UPSTREAM_DATA=`cat /dev/urandom | tr -dc 'a-zA-Z0-9-_!@#$%^&*()_+{}|:<>?='|fold -w $UPSTREAM_LEN| head -n 1`
+	fi
+
+
+
+	START=$((RANDOM%134217727)) # (1Gib-1byte) - if the end range falls outside 1Gib we'll just be served the remaining 1 byte
+	END=$(( $START + $CHUNKS)) # Calculate the end of the range
+
+	echo "Requesting range $START-$END (Chunk size $CHUNKS bytes) from $REMOTE_FILE"
+
+	if [[ "$SEND_DATA" == "y" ]]
+	then
+		echo "Sending $UPSTREAM_LEN bytes of meaningless data with the request"
+	fi
+
+	placeRequest "$REMOTE_FILE" "$HTTP_HOSTNAME" "$START" "$END" "$SEND_DATA" "$UPSTREAM_DATA"
+
+	DELAY=$((RANDOM%$MAX_DELAY)) # Work out how long to delay the next request by
+	echo "Waiting $DELAY seconds until next request"
+	echo 
+	sleep $DELAY
+
+done
+
+
+
+
+
+

--- /dev/null
+++ b/server-side/config
@@ -1,1 +1,9 @@
+#
+# Config file for the server-side Haystack generation scripts
+#
+#
 
+OUTPUT_FILE='/path/to/some/file' # The file to write the data into
+DATA_SOURCE='/dev/urandom' # Where to get the data from
+
+

--- /dev/null
+++ b/server-side/gen_haystack_file.sh
@@ -1,1 +1,15 @@
+#!/bin/bash
+#
+#
+#
 
+mydir=`dirname $0`
+
+# Load the config
+
+source "$mydir/config"
+
+
+
+dd if=$DATA_SOURCE of=$OUTPUT_FILE bs=1M count=1024
+