🢀︎ random :: e66f25f


commit e66f25f121546c821f38150b73ed4981674720ee
Author: acidvegas <acid.vegas@acid.vegas>
Date:   Thu Jun 27 22:39:56 2019 -0400

    Initial commit

diff --git a/2fa.py b/2fa.py
new file mode 100644
index 0000000..c11897f
--- /dev/null
+++ b/2fa.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# Two-factor Authentication (2FA) Helper - Developed by acidvegas in Python (https://acid.vegas/random)
+
+'''
+Requirements:
+	pyotp  (https://pypi.org/project/pyotp/)
+	qrcode (https://pypi.org/project/qrcode/)
+'''
+
+import io, sys, time
+
+try:
+	import pyotp, qrcode
+except ImportError:
+	raise SystemExit('missing required \'pyotp\' module! (https://pypi.org/project/pyotp/)')
+try:
+	import qrcode
+except ImportError:
+	raise SystemExit('missing required \'qrcode\' module! (https://pypi.org/project/qrcode/)')
+
+def qrgen(data):
+	stdout = sys.stdout
+	sys.stdout = io.StringIO()
+	qr = qrcode.QRCode(border=1)
+	qr.add_data(data)
+	qr.make(fit=True)
+	qr.print_ascii(invert=True)
+	output = sys.stdout.getvalue()
+	sys.stdout = stdout
+	return output
+
+name = input('name   : ')
+issuer = input('issuer : ')
+secret = input('secret : ') or pyotp.random_base32()
+uri = pyotp.totp.TOTP(secret).provisioning_uri(name, issuer)
+qr = qrgen(uri).replace(' ', ' ')[:-1]
+max_len = len(qr.split('\n')[1])
+print(uri+'\n'+qr)
+del name, issuer, uri, qr
+while True:
+	code = pyotp.TOTP(secret).now()
+	seconds = int(time.strftime('%S'))
+	remain = 60-seconds if seconds >= 30 else 30-seconds
+	print(f'{code} ({remain})'.center(max_len),  end='\r')
+	time.sleep(1)
\ No newline at end of file
diff --git a/acidbox/.bashrc b/acidbox/.bashrc
new file mode 100644
index 0000000..2a0c08e
--- /dev/null
+++ b/acidbox/.bashrc
@@ -0,0 +1,54 @@
+[[ $- != *i* ]] && return
+
+export LC_CTYPE=en_US.UTF-8
+export LC_ALL=en_US.UTF-8
+
+alias backup='rm ~/.backup/*.tar.gz && tar cvf ~/.backup/backup-DATE,tar.gz ~/'
+alias cmds='sh ~/.scripts/cmds'
+alias colors='sh ~/.scripts/colors.sh'
+alias contact='sh ~/.scripts/contact'
+alias diff='diff --color=auto'
+alias dvtm-help='cat ~/.scripts/dvtm-help'
+alias grep='grep --color=auto'
+alias ls='ls --color=auto'
+alias rtach='abduco -a main'
+alias rules='sh ~/.scripts/rules'
+alias startx='abduco -c main sh ~/.scripts/dvtm-status.sh'
+alias tb='(exec 3<>/dev/tcp/termbin.com/9999; cat >&3; cat <&3; exec 3<&-)'
+alias title='echo -ne "\033]0;$*\007"'
+alias vhosts='sh ~/.scripts/vhosts'
+
+extract () {
+	if [ -f $1 ] ; then
+		case $1 in
+			*.tar.bz2) tar xjvf $1   ;;
+			*.tar.gz)  tar xzvf $1   ;;
+			*.bz2)     bzip2 -d $1   ;;
+			*.rar)     unrar2dir $1  ;;
+			*.gz)      gunzip $1     ;;
+			*.tar)     tar xf $1     ;;
+			*.tbz2)    tar xjf $1    ;;
+			*.tgz)     tar xzf $1    ;;
+			*.zip)     unzip2dir $1  ;;
+			*.Z)       uncompress $1 ;;
+			*.7z)      7z x $1       ;;
+			*.ace)     unace x $1    ;;
+			*)         echo "unkown archive format" ;;
+		esac
+	else
+		echo "'$1' is not a valid file"
+	fi
+}
+
+rnd() {
+	cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $1 | head -n 1
+}
+
+transfer() {
+	tmpfile=$( mktemp -t transferXXX )
+	curl -H "Max-Downloads: 1" -H "Max-Days: 1" --progress-bar --upload-file $1 https://transfer.sh/$(basename $1) >> $tmpfile;
+	cat $tmpfile;
+	rm -f $tmpfile;
+}
+
+PS1='\e[1;34m> \e[0;32m\w \e[0;37m: '
diff --git a/acidbox/.scripts/cmds b/acidbox/.scripts/cmds
new file mode 100755
index 0000000..f2e1707
--- /dev/null
+++ b/acidbox/.scripts/cmds
@@ -0,0 +1,21 @@
+#! /bin/sh
+BLUE='\033[1;34m'
+CYAN='\033[0;36m'
+GREY='\033[1;30m'
+RESET='\033[0m'
+YELLOW='\033[0;33m'
+echo -e "\n[${BLUE}INFORMATION COMMANDS${RESET}]"
+echo -e " ${GREY}* ${CYAN}colors${YELLOW}\tDisplay terminal color support"
+echo -e " ${GREY}* ${CYAN}contact${YELLOW}\tInformation on how to contact the system administrator"
+echo -e " ${GREY}* ${CYAN}rules${YELLOW}\tDisplay the server rules"
+echo -e " ${GREY}* ${CYAN}vhosts${YELLOW}\tList all of the Virtual Hosts"
+echo -e "\n${RESET}[${BLUE}SESSION COMMANDS${RESET}]"
+echo -e " ${GREY}* ${CYAN}dvtm-help${YELLOW}\tInformation about dvtm and how to use it"
+echo -e " ${GREY}* ${CYAN}rtach${YELLOW}\tReattach to your main abduco session ${GREY}(Create session with startx)"
+echo -e " ${GREY}* ${CYAN}startx${YELLOW}\tStart a dvtm session in abduco ${GREY}(See dvtm-help for more information)"
+echo -e "\n${RESET}[${BLUE}OTHER COMMANDS${RESET}]"
+echo -e " ${GREY}* ${CYAN}backup${YELLOW}\tCreate a backup tar file of your home directory ${GREY}(Saves to the ~/.backup/ directory)"
+echo -e " ${GREY}* ${CYAN}extract${YELLOW}\tExtract any archive format ${GREY}(Usage: extract archive.tar.gz)"
+echo -e " ${GREY}* ${CYAN}rnd${YELLOW}\t\tReturn a random string ${GREY}(Usage: rnd <int>)"
+echo -e " ${GREY}* ${CYAN}tb${YELLOW}\t\tUpload a text files contents to termbin ${GREY}(Usage: cat file.txt | tb)"
+echo -e " ${GREY}* ${CYAN}transfer${YELLOW}\tUpload a file to transfer.sh ${GREY}(Usage: transfer file.tar)\n"
diff --git a/acidbox/.scripts/contact b/acidbox/.scripts/contact
new file mode 100755
index 0000000..5224f4a
--- /dev/null
+++ b/acidbox/.scripts/contact
@@ -0,0 +1,12 @@
+#! /bin/sh
+BLUE='\033[1;34m'
+CYAN='\033[0;36m'
+GREY='\033[1;30m'
+RESET='\033[0m'
+YELLOW='\033[0;33m'
+echo -e "\n[${BLUE}CONTACT${RESET}]"
+echo -e " ${GREY}* ${CYAN}E-Mail${YELLOW}\tacid.vegas@acid.vegas"
+echo -e " ${GREY}* ${CYAN}Github${YELLOW}\thttps://github.com/acidvegas"
+echo -e " ${GREY}* ${CYAN}IRC${YELLOW}\t\tirc.supernets.org #acidbox"
+echo -e " ${GREY}* ${CYAN}Keybase${YELLOW}\thttps://keybase.io/acidvegas"
+echo -e " ${GREY}* ${CYAN}Twitter${YELLOW}\thttps://twitter.com/acidvegas\n"
diff --git a/acidbox/.scripts/rules b/acidbox/.scripts/rules
new file mode 100755
index 0000000..b7d96f0
--- /dev/null
+++ b/acidbox/.scripts/rules
@@ -0,0 +1,11 @@
+#! /bin/sh
+BLUE='\033[1;34m'
+CYAN='\033[0;36m'
+GREY='\033[1;30m'
+RESET='\033[0m'
+YELLOW='\033[0;33m'
+echo -e "\n[${BLUE}RULES${RESET}]"
+echo -e " ${GREY}*${YELLOW} This is a private system that you are not to give out access to anyone"
+echo -e "   without permission from the system admin. No illegal files or activites."
+echo -e " ${GREY}*${YELLOW} Avoid denial of service attacks out of respect for other users on the system."
+echo -e " ${GREY}*${YELLOW} Stay in your home directory, keep the system clean, and make regular backups.\n"
diff --git a/acidbox/.scripts/vhosts b/acidbox/.scripts/vhosts
new file mode 100755
index 0000000..8bcd0fc
--- /dev/null
+++ b/acidbox/.scripts/vhosts
@@ -0,0 +1,12 @@
+#! /bin/sh
+BLUE='\033[1;34m'
+CYAN='\033[0;36m'
+GREY='\033[1;30m'
+RESET='\033[0m'
+YELLOW='\033[0;33m'
+echo -e "\n[${BLUE}VIRTUAL HOSTS${RESET}]"
+echo -e " ${GREY}* ${CYAN}ip address 1 ${YELLOW}\tvirtual.hostname1.com"
+echo -e " ${GREY}* ${CYAN}ip address 2 ${YELLOW}\tvirtual.hostname2.com"
+echo -e " ${GREY}* ${CYAN}ip address 3 ${YELLOW}\tvirtual.hostname3.com"
+echo -e " ${GREY}* ${CYAN}ip address 4 ${YELLOW}\tvirtual.hostname4.com"
+echo -e " ${GREY}* ${CYAN}ip address 5 ${YELLOW}\tvirtual.hostname5.com\n"
diff --git a/acidbox/setup b/acidbox/setup
new file mode 100755
index 0000000..aa27fa6
--- /dev/null
+++ b/acidbox/setup
@@ -0,0 +1,46 @@
+#!/bin/sh
+set -e
+
+function setup_motd() {
+	RESET='\033[0m'
+	GREEN='\033[0;32m'
+	BGREEN='\033[1;32m'
+	YELLOW='\033[0;33m'
+	CYAN='\033[0;36m'
+	GREY='\033[1;30m'
+	RED='\033[1;31m'
+	BLUE='\033[1;34m'
+	UBLUE='\033[4;34m'
+	echo "╔═══════════════════════╦══════════════════════════════════════════════════════════════╗
+║${GREEN}  ▄▄▄·  ▄▄· ▪  ·▄▄▄▄   ${RESET}║                    ${RED}Connection Notice${RESET}                         ║
+║${GREEN} ▐█ ▀█ ▐█ ▌▪██ ██▪ ██  ${RESET}╟──────────────────────────────────────────────────────────────╢
+║${GREEN} ▄█▀▀█ ██ ▄▄▐█·▐█· ▐█▌ ${RESET}║                                                              ║
+║${GREEN} ▐█ ▪▐▌▐███▌▐█▌██. ██  ${RESET}║ ${YELLOW}This system is for the use of authorized users only.${RESET}         ║
+║${GREEN}  ▀  ▀ ·▀▀▀ ▀▀▀▀▀▀▀▀•  ${RESET}║ ${YELLOW}All connections will be monitored and logged by the system.${RESET}  ║
+║${GREEN} ▄▄▄▄·       ▐▄• ▄     ${RESET}║                                                              ║
+║${GREEN} ▐█ ▀█▪▪      █▌█▌▪    ${RESET}║ ${YELLOW}Connection issues? Contact ${UBLUE}${BLUE}acid.vegas@acid.vegas${YELLOW} for help.${RESET}   ║
+║${GREEN} ▐█▀▀█▄ ▄█▀▄  ·██·     ${RESET}║                                                              ║
+║${GREEN} ██▄▪▐█▐█▌.▐▌▪▐█·█▌    ${RESET}║ ${YELLOW}Right about now, the funk soul brudda. Check it out now...${RESET}   ║
+║${GREEN} ·▀▀▀▀  ▀█▄▀▪•▀▀ ▀▀    ${RESET}║                                                              ║
+╚═══════════════════════╩══════════════════════════════════════════════════════════════╝" > /etc/issue
+	echo "${YELLOW}Hello ${CYAN}$(whoami)${YELLOW}! You are now connected to ${RED}$(hostname)
+${YELLOW}Type ${BGREEN}cmds${YELLOW} to see a list of commands available.${RESET}
+
+[${BLUE}RULES${RESET}]
+ ${GREY}*${YELLOW} This is a private system that you are not to give out access to anyone
+   without permission from the system admin. No illegal files or activites.
+ ${GREY}*${YELLOW} Avoid denial of service attacks out of respect for other users on the system.
+ ${GREY}*${YELLOW} Stay in your home directory, keep the system clean, and make regular backups." > /etc/motd
+}
+
+function setup_user() {
+	sudo useradd -m -G ssh -s /bin/bash $1
+	mkdir /home/$1/.scripts
+	wget -O /home/$1/.bashrc             https://git.supernets.org/acidvegas/acidbox/blob/master/files/.bashrc
+	wget -O /home/$1/.scripts/cmds       https://git.supernets.org/acidvegas/acidbox/blob/master/files/cmds
+	wget -O /home/$1/.scripts/contact    https://git.supernets.org/acidvegas/acidbox/blob/master/files/contact
+	wget -O /home/$1/.scripts/rules      https://git.supernets.org/acidvegas/acidbox/blob/master/files/rules
+	wget -O /home/$1/.scripts/vhosts     https://git.supernets.org/acidvegas/acidbox/blob/master/files/vhosts
+	echo "clear && reset" > /home/$1/.bash_logout
+	echo "[[ -f ~/.bashrc ]] && . ~/.bashrc" > /home/$1/.bash_profile
+}
\ No newline at end of file
diff --git a/btkb.sh b/btkb.sh
new file mode 100644
index 0000000..6b56fa3
--- /dev/null
+++ b/btkb.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+sudo pacman -S bluez bluez-utils
+sudo systemctl enable bluetooth && sudo systemctl start bluetooth
+sudo sed -i 's/#AutoEnable=false/AutoEnable=true/' /etc/bluetooth/main.conf
+bluetoothctl power on
+bluetoothctl agent KeyboardOnly
+bluetoothctl pairable on
+bluetoothctl scan on
+bluetoothctl pair CC:C5:0A:20:91:5B
+bluetoothctl trust CC:C5:0A:20:91:5B
+bluetoothctl connect CC:C5:0A:20:91:5B
+bluetoothctl scan off
\ No newline at end of file
diff --git a/clitter.py b/clitter.py
new file mode 100644
index 0000000..217888d
--- /dev/null
+++ b/clitter.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+# CLI Twitter - Developed by acidvegas in Python (https://acid.vegas/random)
+
+'''
+Requirements:
+	Tweepy (http://pypi.python.org/pypi/tweepy)
+'''
+
+import sys
+
+consumer_key        = 'CHANGEME'
+consumer_secret     = 'CHANGEME'
+access_token        = 'CHANGEME'
+access_token_secret = 'CHANGEME'
+
+if len(sys.argv) < 2:
+	raise SystemExit('[!] - Missing command line arguments! (Usage: clitter.py <tweet>)')
+else:
+	tweet = ' '.join(sys.argv[1:])
+try:
+	import tweepy
+except ImportError:
+	raise SystemExit('[!] - Failed to import the Tweepy library! (http://pypi.python.org/pypi/tweepy)')
+try:
+	auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
+	auth.set_access_token(access_token, access_token_secret)
+	api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
+	if not api.verify_credentials():
+		raise tweepy.TweepError
+except tweepy.TweepError as ex:
+	raise SystemExit(f'[!] - Failed to login to Twitter! ({ex})')
+else:
+	me = api.me()
+if len(tweet) > 280:
+	raise SystemExit('[!] - Tweet is too long!')
+else:
+	try:
+		api.update_status(tweet)
+		tweet = api.user_timeline(id=me.id, count=1)[0]
+		print(f'[+] - Tweet has been posted! (https://twitter.com/{me.screen_name}/status/{tweet.id})')
+	except tweepy.TweepError as ex:
+		raise SystemExit(f'Failed to post Tweet! ({ex})')
\ No newline at end of file
diff --git a/craggle.py b/craggle.py
new file mode 100644
index 0000000..3a08a12
--- /dev/null
+++ b/craggle.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# CraigsList Parser - Developed by acidvegas in Python (https://acid.vegas/random)
+
+'''
+Random script to parse all the countries, states, cities, & sections/sub-sections on CraigsList
+'''
+
+import re, time, urllib.request
+
+def between(source, start, stop):
+	data = re.compile(start + '(.*?)' + stop, re.IGNORECASE|re.MULTILINE).search(source)
+	return data.group(1) if data else False
+
+def get_source(url):
+	source = urllib.request.urlopen(url, timeout=10)
+	charset = source.headers.get_content_charset()
+	return source.read().decode(charset) if charset else source.read().decode()
+
+db        = {'category':dict(),'subcat':dict()}
+source    = get_source('http://www.craigslist.org/about/sites?lang=en&cc=us')
+countries = re.findall('<h1><a name="(.*?)"></a>(.*?)</h1>', source, re.IGNORECASE|re.MULTILINE)
+source    = source.replace('\n', '').replace('\r','')
+main_data = dict()
+statess = 0
+citiess = 0
+for country in countries:
+	main_data[country[0].lower()] = dict()
+	data   = between(source, '<h1><a name="{0}"></a>{1}</h1>'.format(country[0], country[1]),'</a></li>                    </ul>                </div>            </div>')
+	states = re.findall('<h4>(.*?)</h4>', data, re.IGNORECASE|re.MULTILINE)
+	statess += len(states)
+	for state in states:
+		main_data[country[0].lower()][state.lower()] = dict()
+		state_data = between(source, f'<h4>{state}</h4>', '</ul>')
+		cities = re.findall('<li><a href="(.*?)">(.*?)</a></li>', state_data, re.IGNORECASE|re.MULTILINE)
+		citiess += len(cities)
+		for city in cities:
+			main_data[country[0].lower()][state.lower()][city[1]] = city[0].split('/?')[0]
+			new_source = get_source(city[0].split('/?')[0])
+			new_source = new_source.replace('\n', '').replace('\r','')
+			categories = re.findall('data-alltitle="all (.*?)" data-cat="(.*?)">', new_source, re.IGNORECASE|re.MULTILINE)
+			for category in categories:
+				db['category'][category[0]] = db['category'][category[0]]+1 if category[0] in db['category'] else 1
+				if category[0] != 'resumes':
+					cat = category[0].replace(' ','-')
+					category_data  = between(new_source, f'<h4 class="ban"><a href="/d/{cat}/search', '</ul></div></div>')
+					try:
+						sub_categories = re.findall('span class="txt">(.*?)<sup class', category_data, re.IGNORECASE|re.MULTILINE)
+						for sub_category in sub_categories:
+							print(f'{country[1]} | {state} | {city[1]} | {category[0]} | {sub_category}')
+							db['subcat'][sub_category] = db['subcat'][sub_category]+1 if sub_category in db['subcat'] else 1
+					except:
+						print('\n\n\nerror !!!')
+						print(category_data)
+						print(category)
+						input('')
+print(f'Country : {len(main_data)}')
+print(f'State   : {statess}')
+print(f'City    : {citiess}')
+print(str(db['category']))
+print('\n\n\n')
+print(str(db['subcat']))
diff --git a/docs/gpg.md b/docs/gpg.md
new file mode 100644
index 0000000..af24aba
--- /dev/null
+++ b/docs/gpg.md
@@ -0,0 +1,74 @@
+# Create a key
+`gpg --expert --full-generate-key`
+* RSA (set your own capabilities)
+* Set to Certify only.
+* 4096
+* 2020-01-01
+
+`gpg --expert --edit-key <userid>`
+* `addkey` (Create 3, one for sign, encrypt, authenticate)
+* `adduid`
+* `save`
+
+# Backup key
+* `mv ~/.gnupg/secring.gpg ~/.backup/gpg/`
+* `mv ~/.gnupg/pubring.gpg ~/.backup/gpg/`
+* `gpg -a --export-secret-key <userid> > secret_key.gpg`
+* `gpg -a --export-secret-subkeys <userid> > secret_subkeys.gpg`
+* `gpg --delete-secret-keys <userid>`
+* `gpg --import secret_subkeys.gpg`
+* `gpg --list-secret-keys`
+* `rm secret_subkeys.gpg`
+
+# Revoke cert
+* `gpg -a --output revoke.asc --gen-revoke '<fingerprint>'`
+
+# Import/Export public key
+* `gpg --import public.key`
+* `gpg --output public.key --armor --export <userid>`
+
+# Import/Export private key
+* `gpg --export-secret-keys --armor <userid> > privkey.asc`
+* `gpg --import privkey.asc`
+
+# Edit keys
+* `gpg --edit-key <userid>`
+
+# List (secret) keys
+* `gpg --list-keys`
+* `gpg --list-secret-keys`
+
+# Encrypt/Decrypt
+* `gpg --recipient user-id --encrypt doc`
+* `gpg --output doc --decrypt doc.gpg`
+
+or...
+
+* `gpg -c --s2k-cipher-algo AES256 --s2k-digest-algo SHA512 --s2k-count 65536 doc`
+* `gpg --output doc --decrypt doc.gpg`
+
+# Signing
+* `gpg --output doc.sig --sign doc`
+* `gpg --output doc.sig --clearsign doc`
+* `gpg --output doc.sig --detach-sig doc`
+
+# Verify
+* `gpg --verify doc.sig`
+* `gpg --verify archlinux-version.iso.sig`
+* `gpg --verify archlinux-version.iso.sig /path/to/archlinux-version.iso`
+* `gpg --with-fingerprint <keyfile>`
+
+# Send keys
+* `gpg --send-keys <userid>`
+* `gpg --refresh-keys`
+
+# Get keys
+* `gpg --recv-key '<fingerprint>'`
+* `gpg --fingerprint '<fingerprint>'`
+
+# Sign key
+* `gpg --lsign-key '<fingerprint>'`
+
+or...
+
+* `gpg --sign-key '<fingerprint>'`
\ No newline at end of file
diff --git a/docs/ssh.md b/docs/ssh.md
new file mode 100644
index 0000000..d3fd080
--- /dev/null
+++ b/docs/ssh.md
@@ -0,0 +1,273 @@
+A full write-up on OpenSSH usage with security in mind.
+
+---
+
+# Table of Contents
+* [Generating An SSH Key Pair](#generating-an-ssh-key-pair)
+	- [Linux](#linux)
+	- [Windows](#windows)
+* [Getting Your Client To Use Your SSH Key](#getting-your-client-to-use-your-ssh-key)
+	- [Linux](#linux)
+	- [Windows](#windows)
+* [Setup Server](#setup-server)
+	- [Harden OpenSSH Daemon](#harden-openssh-daemon)
+	- [Create A New User On The Server](#create-a-new-user-on-the-server)
+	- [Copy Your Public Key To Your Shell](#copy-your-public-key-to-your-shell)
+* [Extra Security](#extra-security)
+	- [Allow Incoming SSH Connections Through IPTables](#allow-incoming-ssh-connections-through-iptables)
+	- [Lock Users In A Chroot Jail Environment](#lock-users-in-a-chroot-jail-environment)
+	- [Port Knocking](#port-knocking)
+		- [Setup Server](#setup-server-1)
+			- [Using IPTables](#using-iptables)
+			- [Using Knockd](#using-knockd)
+		- [Knocking Your Server](#knocking-your-server)
+			- [Using Nmap](#using-nmap)
+			- [Using knockd](#using-knockd-1)
+	- [Jump Hosts](#jump-hosts)
+
+**Note:** The port *65150* is used in this write-up as an example of how to use a non-standard ports.
+
+---
+
+## Generating An SSH Key Pair
+### Linux
+Generate a key using the **Ed25519** algorithm with 500 KDF rounds:
+* `ssh-keygen -t ed25519 -a 500 -C "$(whoami)@$(hostname)-$(date -I)"`
+
+This will generate 2 files in your `~/.ssh` directory. A public key *(.pub)* and a private key.
+
+You only need to backup your private key. Public keys can be regenerated from the private key:
+* `ssh-keygen -y -f ~/.ssh/acidvegas@pi-2017-01-01`
+
+Copy your public key to clipboard:
+* `cat ~/.ssh/acidvegas@pi-2017-01-01.pub`
+
+### Windows
+Download & run [puttygen](https://the.earth.li/~sgtatham/putty/latest/w32/puttygen.exe).
+
+Once opened, change the key type to **ED25519** under the *Parameters* box, and then click the *Generate* button.
+
+Click the *Save private key* button to save your key.
+
+You only need to backup your private key. Public keys can be regenerated by clicking `File -> Load private key`.
+
+Copy the data in the box labeled *Public key for pasting into OpenSSH authorized_keys file*.
+
+## Getting Your Client To Use Your SSH Key
+### Linux
+* `ssh -p 65150 -i ~/.ssh/acidvegas@pi-2017-01-01 acidvegas@192.168.1.10`
+
+or...
+
+* `nano ~/.ssh/config`
+```
+Host acidbox
+	HostName 192.168.1.10
+	Port 65150
+	User acidvegas
+	IdentityFile ~/.ssh/acidvegas@pi-2017-01-01
+	IdentitiesOnly yes
+```
+* `chmod 600 ~/.ssh/config`
+* Usage: `ssh acidbox`
+
+### Windows
+Download & run the [putty](https://the.earth.li/~sgtatham/putty/latest/w32/putty.exe) client.
+
+Once opened, select `Connection -> SSH -> Auth` from the *Category* box. Click the *Browse* button and select your private key.
+
+Select *Session* from the *Category* box. Change the *Host Name (or IP address)* and *Port* to your server.
+
+Name the session in *Saved Sessions* box and click the *Save* button.
+
+SSH into your server by clicking your saved session from the *Saved Sessions* box, and clicking the *Open* button.
+
+---
+
+## Setup Server
+### Harden OpenSSH Daemon
+* `nano /etc/ssh/sshd_config`
+```
+AddressFamily any
+AllowAgentForwarding no
+AllowGroups ssh
+AllowTcpForwarding no
+AuthorizedKeysFile /etc/ssh/authorized_keys/%u
+#Banner /etc/issue
+ChallengeResponseAuthentication no
+Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
+ClientAliveInterval 0
+#ClientAliveCountMax 0
+HostKey /etc/ssh/ssh_host_ed25519_key
+KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
+LoginGraceTime 30
+MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
+MaxAuthTries 2
+MaxSessions 1
+MaxStartups 3:50:10
+PasswordAuthentication no
+PermitRootLogin no
+Port 65150
+PrintLastLog no
+PrintMotd no
+Protocol 2
+```
+* `mkdir /etc/ssh/authorized_keys`
+* `rm /etc/ssh/ssh_host_*_key`
+* `ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key`
+
+**Options**:
+* The `AddressFamily` option can be:
+	- **inet** for IPv4 only.
+	- **inet6** for IPv6 only.
+	- **any** for both.
+* The `AuthorizedKeysFile` option can be commented out to use the standard `~/.ssh/authorized_keys` file instead.
+* The `Banner` option can be un-commented if the `/etc/issue` file exists. This is shown before the user authenticates.
+* The `ClientAliveCountMax` option can be un-commented & the `ClientAliveInterval` option can be changed to **1800** to enforce a 15 minute idle timeout.
+* The `MaxSessions` option can be increased if there are additional users on the server.
+* The `Port` option should be set to a non-standard port *(High-value port number recommended)*. 
+* The `PrintMotd` option can be changed to **yes** if the file `/etc/motd` exists. This is shown after the user authenticates.
+
+### Create A New User On The Server
+Create a new user on the server with a password:
+* `useradd -m -s /bin/bash acidvegas`
+* `passwd acidvegas`
+
+Create an **ssh** group and add your user to the group.
+* `groupadd ssh`
+* `gpasswd -a acidvegas ssh`
+
+### Copy Your Public Key To Your Shell
+* `nano /etc/ssh/authorized_keys/acidvegas` *(Paste your public key data in this file)*
+
+**Note:** This is only required if you are using the `AuthorizedKeysFile /etc/ssh/authorized_keys/%u` line in your `sshd_config` file. For using the standard `~/.ssh/authorized_keys` file, do the follow:
+* `mkdir ~/.ssh`
+* `chmod 700 ~/.ssh`
+* `chown -R $USER ~/.ssh`
+* `nano ~/.ssh/authorized_keys` *(Paste the copied public key data into this file)*
+* `chmod 400 ~/.ssh/authorized_keys`
+* Optionally, you can pass the immutable flag to prevent changes:
+	- `chattr +i ~/.ssh`
+	- `chattr +i ~/.ssh/authorized_keys`
+
+---
+
+# Extra Security
+### Allow Incoming SSH Connections Through IPTables
+```
+iptables -A INPUT  -i eth0 -p tcp --dport 65150 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
+iptables -A OUTPUT -o eth0 -p tcp --sport 65150 -m conntrack --ctstate ESTABLISHED     -j ACCEPT
+```
+
+You can also allow only incomming connection from a specific IP address instead by changing the first line above to:
+```
+iptables -A INPUT -i eth0 -p tcp -s 192.168.1.99 --dport 65150 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
+```
+
+### Lock Users In A Chroot Jail Environment
+See [mkchroot](https://github.com/acidvegas/mkchroot) repository for details.
+
+### Port Knocking
+The following is an example which uses the port knocking sequence `8881 -> 7777 -> 9991` to open port 65150 for 30 seconds.
+
+##### Server 
+###### Using IPTables
+* `nano /etc/iptables/iptables.rules`
+```
+*filter
+:INPUT DROP [0:0]
+:FORWARD DROP [0:0]
+:OUTPUT ACCEPT [0:0]
+:TRAFFIC - [0:0]
+:SSH-INPUT - [0:0]
+:SSH-INPUTTWO - [0:0]
+# TRAFFIC chain for Port Knocking. The correct port sequence in this example is  8881 -> 7777 -> 9991; any other sequence will drop the traffic 
+-A INPUT -j TRAFFIC
+-A TRAFFIC -p icmp --icmp-type any -j ACCEPT
+-A TRAFFIC -m state --state ESTABLISHED,RELATED -j ACCEPT
+-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 65150 -m recent --rcheck --seconds 30 --name SSH2 -j ACCEPT
+-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH2 --remove -j DROP
+-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 9991 -m recent --rcheck --name SSH1 -j SSH-INPUTTWO
+-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH1 --remove -j DROP
+-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 7777 -m recent --rcheck --name SSH0 -j SSH-INPUT
+-A TRAFFIC -m state --state NEW -m tcp -p tcp -m recent --name SSH0 --remove -j DROP
+-A TRAFFIC -m state --state NEW -m tcp -p tcp --dport 8881 -m recent --name SSH0 --set -j DROP
+-A SSH-INPUT -m recent --name SSH1 --set -j DROP
+-A SSH-INPUTTWO -m recent --name SSH2 --set -j DROP 
+-A TRAFFIC -j DROP
+COMMIT
+```
+* `systemctl daemon-reload `
+* `systemctl restart iptables`
+
+###### Using Knockd
+Download & install the [knockd](http://www.zeroflux.org/projects/knock) package.
+
+* `nano /etc/knockd.conf`
+```
+[options]
+	logfile = /var/log/knockd.log
+[opencloseSSH]
+	sequence      = 8881:tcp,7777:tcp,9991:tcp
+	seq_timeout   = 5
+	tcpflags      = syn,ack
+	start_command = /usr/bin/iptables -A TCP -s %IP% -p tcp --dport 65150 -j ACCEPT
+	cmd_timeout   = 10
+	stop_command  = /usr/bin/iptables -D TCP -s %IP% -p tcp --dport 65150 -j ACCEPT
+```
+
+##### Knocking Your Server
+###### Using Nmap
+Download & install the [nmap](https://nmap.org/) package.
+
+* `nano knock.sh`
+```bash
+#!/bin/bash
+HOST=$1
+shift
+for ARG in "$@"
+do
+	nmap -Pn --host_timeout 100 --max-retries 0 -p $ARG $HOST
+done
+```
+* Usage: `sh knock.sh example.server.com 8881 7777 9991`
+
+###### Using Knockd
+Download & install the [knockd](http://www.zeroflux.org/projects/knock) package.
+
+* `knock -v example.server.com 8881:tcp 7777:tcp 9991:tcp`
+
+### Jump Hosts
+* `ssh -J <jumphost> <host>`
+
+The `<jumphost>` option can be `user@host`, `user@host:port` or an host setup in your `~/.ssh/config`.
+
+Multiple jump hosts can be used in a comma *(no spaces)* separated list.
+
+The same applies for the `<host>` option, except to change the port, either use the `-p <port>` option at the end or use a host setup in your `~/.ssh/config`.
+
+or...
+
+* nano `~/.ssh/config`:
+```
+Host jumpbox
+    HostName jump.server.com
+
+Host targetbox
+	...
+    ProxyJump jumpbox1
+	...
+```
+
+Multiple jump hosts can be used in the `ProxyJump` option in a comma *(no spaces)* separated list.
+
+Connect to your target host with `ssh targetbox`
+
+---
+
+## Sources
+* https://wiki.archlinux.org/index.php/Port_knocking
+* https://wiki.archlinux.org/index.php/SSH_keys
+* https://wiki.mozilla.org/Security/Guidelines/OpenSSH
+* https://www.openssh.com/manual.html
+* https://stribika.github.io/2015/01/04/secure-secure-shell.html
diff --git a/gitremote.sh b/gitremote.sh
new file mode 100644
index 0000000..ce6bb3f
--- /dev/null
+++ b/gitremote.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+for u in $HOME/dev/git/*/; do
+	for d in $(find $u -name .git -type d -prune | sort); do
+		u=$(basename $u)
+		r=$(basename -s .git `git --git-dir $d config --get remote.origin.url`)
+		echo "updating $r..."
+		git -C $d remote remove origin
+		git -C $d remote add origin git@github.com:$s/$r.git
+		git -C $d remote set-url --add --push origin git@github.com:$u/$r.git
+		git -C $d remote set-url --add --push origin git@gitlab.com:$u/$r.git
+		git -C $d remote set-url --add --push origin git@contra:$r.git
+	done
+done
\ No newline at end of file
diff --git a/gitserver.sh b/gitserver.sh
new file mode 100644
index 0000000..08b3d66
--- /dev/null
+++ b/gitserver.sh
@@ -0,0 +1,7 @@
+#/bin/sh
+[ ! getent group ssh                       ] && groupadd ssh
+[ ! grep -q /usr/bin/git-shell /etc/shells ] && echo /usr/bin/git-shell >> /etc/shells
+[ ! $(getent passwd git > /dev/null)       ] && userdel -f git
+useradd -d /srv/git -G ssh -k /dev/null -m -s /usr/bin/git-shell -U git
+echo "PUBLICKEY" > /etc/ssh/authorized_keys/git
+mkdir "$1.git" && cd "$1.git" && git -C "$1.git" --bare init chown -R git:git "$1.git"
\ No newline at end of file
diff --git a/irc/anythinggoes/anythinggoes.py b/irc/anythinggoes/anythinggoes.py
new file mode 100644
index 0000000..5a425b5
--- /dev/null
+++ b/irc/anythinggoes/anythinggoes.py
@@ -0,0 +1,265 @@
+# -*- coding: utf-8 -*-
+#!/usr/bin/env python
+# THEGAME IRC Bot - Developed by acidvegas in Python (https://acid.vegas/random)
+import random,socket,ssl,threading,time
+
+# Config
+admin_ident       = 'ak!ak@super.nets'
+channel           = '#anythinggoes'
+nickserv_password = 'CHANGEME'
+operator_password = 'CHANGEME'
+throttle_msg      = 0.15
+
+# Formatting Control Characters / Color Codes
+bold        = '\x02'
+italic      = '\x1D'
+underline   = '\x1F'
+reverse     = '\x16'
+reset       = '\x0f'
+white       = '00'
+black       = '01'
+blue        = '02'
+green       = '03'
+red         = '04'
+brown       = '05'
+purple      = '06'
+orange      = '07'
+yellow      = '08'
+light_green = '09'
+cyan        = '10'
+light_cyan  = '11'
+light_blue  = '12'
+pink        = '13'
+grey        = '14'
+light_grey  = '15'
+
+def color(msg,foreground,background=None):return f'\x03{foreground},{background}{msg}{reset}' if background else f'\x03{foreground}{msg}{reset}'
+def error(msg,reason):print(f'{get_time()} | [!] - {msg} ({reason})')
+def get_time():return time.strftime('%I:%M:%S')
+def random_str(size):return ''.join(random.choice('aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ') for _ in range(size))
+
+class Functions:
+	def banana_bomb():
+		for i in range(random.randint(5,10)):
+			spaces=random.randint(1,120)
+			for line in banana_data:
+				Bot.sendmsg(channel,' '*spaces+line)
+
+	def chat_rain(amount):
+		words = ('ok','tru','same','wow','nice','XD','ok','np','sup','cool','nmu','lol','ah','srry','jk')
+		for i in range(amount):
+			Bot.sendmsg(channel,' '*random.randint(3,25)+random.choice(words)+' '*random.randint(10,50)+random.choice(words)+' '*random.randint(10,50)+random.choice(words))
+
+	def crab_flood(amount):
+		counter=1
+		notify=random.randint(100,999)
+		if amount>=1000000:
+			amount=1000000
+			Bot.sendmsg(channel,color('GENTLEMEN! BEHOLD!',red))
+			Bot.sendmsg(channel,color('THE MILLION CRAB MARCH!',red))
+		for i in range(amount):
+			spaces=random.randint(1,120)
+			for line in crab_data:
+				Bot.sendmsg(channel,' '*spaces+line)
+			counter+=1
+			if counter==notify:
+				spaces=random.randint(1,120)
+				Bot.sendmsg(channel,color(' '*spaces+str(i)+' MOTHER FUCKING CRABS !!!',red))
+				counter=1
+
+	def grave(nick):
+		length=len(nick)
+		Bot.sendmsg(channel,color(' '*(length+8),light_blue,light_blue))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('    ',light_blue,light_blue),color(' ',grey,grey),color(' '*length,light_grey,light_grey),color('    ',light_blue,light_blue)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',light_blue,light_blue),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color('   ',light_blue,light_blue)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',light_green,light_green),color(' ', grey),color('R I P'.center(length+2),black,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',green,green),color(' ', grey),color(nick.upper().center(length+2),black,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',green,green),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}{4}'.format(color(' ',light_green,light_green),color('  ',green,green),color(' ',grey),color('2018'.center(length+2),black,light_grey),color('   ', light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}{4}'.format(color('  ',light_green,light_green),color(' ',green,green),color(' ',grey),color(' '*(length+2),light_grey,light_grey),color('   ',light_green,light_green)))
+		Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(color('   ',light_green,light_green),color(' ', grey),color(' '*(length+2),light_grey,light_grey),color('   ', light_green,light_green)))
+
+	def rain(word,amount):
+		for i in range(amount):
+			Bot.sendmsg(channel,' '*random.randint(3,25)+word+' '*random.randint(10,50)+word+' '*random.randint(10,50)+word)
+
+	def rope(length):
+		spaces=50
+		prev=None
+		for i in range(length):
+			if random.choice((True,False)):
+				if prev!='╱':spaces+=1
+				char='╲'
+			else:
+				if prev!='╲':spaces-=1
+				char='╱'
+			Bot.sendmsg(channel,' '*spaces+char)
+			prev=char
+		Bot.sendmsg(channel,' '*(spaces-2)+'(;))')
+
+	def wave(msg,lines,spaces,hilite):
+		rainbow=['04','08','09','11','12','13']
+		spacer=15
+		spaces+=spacer
+		toggle=True
+		data=list()
+		for i in range(lines):
+			if hilite:
+				Bot.sendmsg(channel,'{0}{1}{2}{3}'.format((Bot.nicks[0]+': ').ljust(spacer),color('░▒▓',rainbow[1]),color(f' {msg} ',rainbow[0],rainbow[1]),color('▓▒░',rainbow[1])))
+				Bot.nicks.append(Bot.nicks.pop(0))
+			else:
+				Bot.sendmsg(channel, '{0}{1}{2}{3}'.format(' '*spacer,color('░▒▓',rainbow[1]),color(f' {msg} ',rainbow[0],rainbow[1]),color('▓▒░',rainbow[1])))
+			rainbow.append(rainbow.pop(0))
+			if toggle:spacer+=1
+			else:spacer-=1
+			if spacer==spaces:toggle=False
+			elif spacer==15:toggle=True
+
+	def worm(length):
+		spacer=random.randint(10,100)
+		Bot.sendmsg(channel,'{0}   {1}{2}'.format(' '*spacer,color('░▒▓',pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0}  {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('  ',black,pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('    ',black,pink),color('▓▒░',pink)))
+		for i in range(length):
+			Bot.sendmsg(channel,'{0}{1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('      ',black,pink),color('▓▒░',pink)))
+			if random.choice((True,False)):spacer += 1
+			else:spacer-=1
+		Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('_  _',black,pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0} {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('o  o',black,pink),color('▓▒░',pink)))
+		Bot.sendmsg(channel,'{0}  {1}{2}{3}'.format(' '*spacer,color('░▒▓',pink),color('  ',black,pink),color('▓▒░',pink)))
+
+class WormNet(threading.Thread):
+	def __init__(self):
+		self.sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
+		threading.Thread.__init__(self)
+	def run(self):
+		Bot.wormnet=True
+		try:
+			self.sock.connect(('wormnet1.team17.com',6667))
+			self.raw('PASS ELSILRACLIHP')
+			self.raw('USER Username hostname servername :48 0 US 3.7.2.1')
+			self.raw('NICK SUPERNETS')
+			while True:
+				data=self.sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split())>=2):
+					Bot.sendmsg_wormnet('raw',cyan,line)
+					args=line.split()
+					if line.startswith('ERROR :Closing Link:'):raise Exception('Connection has closed.')
+					elif args[0]=='PING':self.raw('PONG '+args[1][1:])
+					elif args[1]=='001':self.raw('JOIN '+channel)
+					elif args[1]=='366':Bot.sendmsg_wormnet('join',green,'Joined #anythinggoes channel!')
+		except (UnicodeDecodeError,UnicodeEncodeError):pass
+		except Exception as ex:
+			Bot.sendmsg_wormnet('error',red,'Unknown error occured!',ex)
+			self.sock.close()
+			Bot.wormnet=False
+			Bot.sendmsg_wormnet('disconnected',red,'Lost connection to the WormNet relay!')
+	def raw(self,msg):self.sock.send(bytes(msg+'\r\n','utf-8'))
+	def sendmsg(self,target,msg):self.raw(f'PRIVMSG {target} :{msg}')
+
+class IRC(object):
+	def __init__(self):
+		self.nicks=list()
+		self.echo=False
+		self.sock=None
+		self.wormnet=False
+
+	def connect(self):
+		try:
+			self.sock=ssl.wrap_socket(socket.socket(socket.AF_INET,socket.SOCK_STREAM))
+			self.sock.connect(('irc.supernets.org',6697))
+			self.raw(f'USER THEG 0 * :YOU LOST THE GAME')
+			self.raw('NICK THEGAME')
+			while True:
+				data = self.sock.recv(1024).decode('utf-8')
+				for line in (line for line in data.split('\r\n') if len(line.split()) >= 2):
+					print(f'{get_time()} | [~] - {line}')
+					args = line.split()
+					if args[0]=='PING':self.raw('PONG '+args[1][1:])
+					elif args[1]=='001':
+						self.raw('MODE THEGAME +BDd')
+						self.sendmsg('NickServ','IDENTIFY THEGAME '+nickserv_password)
+						self.raw(f'OPER thegame {operator_password}')
+						self.raw('JOIN '+channel)
+					elif args[1]=='433':self.raw('NICK THE_GAME_'+str(random.randint(10,99)))
+					elif args[1]=='353' and len(args)>=6:self.nicks+=' '.join(args[5:])[2:].split()
+					elif args[1]=='JOIN' and len(args)==3:self.raw('NOTICE {0} :Thank you for joining #AnythingGoes, you have {1} memo(s) waiting. Please type /server MemoServ read to check your messages.'.format(args[0].split('!')[0][1:],color(random.randint(1,3),red)))
+					elif args[1]=='PART' and len(args)>=3:
+						self.sendmsg(args[2],color('EMO-PART DETECTED',red))
+						self.sendmsg(args[0].split('!')[0][1:],'bet u wont come back pussy...')
+					elif args[1]=='PRIVMSG' and len(args)>=4:
+						ident=args[0][1:]
+						nick=args[0].split('!')[0][1:]
+						chan=args[2]
+						msg= ' '.join(args[3:])[1:]
+						if chan==channel:self.event_message(ident,nick,chan,msg)
+					elif args[1]=='QUIT':Functions.grave(args[0].split('!')[0][1:])
+		except(UnicodeDecodeError,UnicodeEncodeError):pass
+		except:self.sock.close()
+		time.sleep(15)
+		self.connect()
+
+	def event_message(self,ident,nick,chan,msg):
+		args=msg.split()
+		if msg[:1]=='!':
+			if msg=='!bananabomb':Functions.banana_bomb()
+			elif msg=='!crate':
+				for line in crate_data:self.sendmsg(channel,line)
+			elif msg=='!echo':
+				self.echo=False if self.echo else True
+			elif msg=='refresh':
+				self.nicks=list()
+				self.raw('NAMES #anythinggoes')