├── .gitignore ├── README.md ├── docs └── images │ ├── proxycannon-ng-visual.png │ ├── sprocket.png │ └── wwhf.png ├── nodes └── aws │ ├── add_route.bash │ ├── configs │ └── node_setup.bash │ ├── del_route.bash │ ├── main.tf │ └── variables.tf └── setup ├── control-server-setup.sh ├── install.sh └── setup-load-balancing.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.tfstate 2 | *.tfstate.backup 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # proxycannon-ng 2 | 3 | >Thank you **Wild West Hackin' Fest** for your help and support in our community-driven hackathon! We've created a on-demand proxy tool that leverages cloud environments giving a user the ability to source (all) your traffic from an endless supply of cloud based IP address. Think of it as your own private TOR network for your redteam and pentest engagements. No more defenses throttling and blocking you! 4 | 5 | ### Initial Release 6 | Code and infrastructure has been developed, tested and proven viable. We're in the process of ironing out final changes and will have commits showing up this weekend (October 27/28). 7 | 8 | **Successes: ** 9 | 10 | - VPN Server Build (scripted) 11 | - Client VPN (Full Tunnel) 12 | - Terraform Node Management (Build, Destroy, Routing) 13 | - AWS Multipath Node Routing (Load Balanced Exit Nodes) 14 | 15 | ### Getting Started 16 | 17 | AWS Management 18 | - Amazon AWS Account (Goal is to support multiple cloud providers, initial release is on AWS) 19 | - Launch (1) Ubuntu Server t1-micro instance, recommend public AMI ami-0f65671a86f061fcd 20 | 21 | Build OpenVPN Server 22 | - cd into setup 23 | - Run setup-load-balancing.sh (From this GIT repo) 24 | 25 | Build Exit Nodes 26 | - perform terraform prerequisites 27 | - cd in nodes/aws then run: 28 | ``` 29 | terraform init 30 | terraform apply 31 | ``` 32 | 33 | ### Project History 34 | 35 | Hackathon sponsored by [Sprocket Security](https://www.sprocketsecurity.com) and hosted at [Wild West Hackin' Fest 2018](https://www.wildwesthackinfest.com) 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 | . 46 | 47 | ### Get Involved 48 | Follow [@sprocketsec](https://www.twitter.com/sprocketsec) on twitter for live updates during the hackathon. 49 | 50 | Join us in [Slack](https://join.slack.com/t/hackfest-hq/shared_invite/enQtNDY1NjA4ODExNzYzLWNjM2EwMDIxN2RmYTgyMjNlMjhjMTgyYzQ0NzZkZGM1OGViOGFmYmMxNzMwZTAzMTlhMTkxODljODc5YTcxZTE) to discuss, contribute and troubleshoot. We'd love to hear from you. 51 | 52 | ### Implementation Diagram 53 | ![proxycannon-ng visual](https://github.com/proxycannon/proxycannon-ng/blob/master/docs/images/proxycannon-ng-visual.png) 54 | 55 | ### Special Thanks 56 | Special thanks to @i128 (@jarsnah12 on twitter) for developing the original proxycannon tool that is our inspirartion. 57 | 58 | ### Developers: 59 | Help a little or a lot and get your name listed here as a developer of an open-source security tool...looks good on a resume and sounds good at the bar ;-) 60 | 61 | [@jarsnah12](https://www.twitter.com/jarsnah12) - original proxycannon v1 author 62 | [@w9hax](https://www.twitter.com/w9hax) - mad openVPN skillz 63 | [@caseycammilleri](https://www.twitter.com/caseycammilleri) - Gets lost deep in iptables 64 | **your name here** 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /docs/images/proxycannon-ng-visual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/secretsquirrel/proxycannon-ng/7d739ad5196c477794250b69e13dd7e85f414efd/docs/images/proxycannon-ng-visual.png -------------------------------------------------------------------------------- /docs/images/sprocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/secretsquirrel/proxycannon-ng/7d739ad5196c477794250b69e13dd7e85f414efd/docs/images/sprocket.png -------------------------------------------------------------------------------- /docs/images/wwhf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/secretsquirrel/proxycannon-ng/7d739ad5196c477794250b69e13dd7e85f414efd/docs/images/wwhf.png -------------------------------------------------------------------------------- /nodes/aws/add_route.bash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | IP=$1 3 | # grab last ran route cmd 4 | ROUTECMD=$(cat .routecmd) 5 | 6 | # is there a last used route cmd 7 | if [ -z "$ROUTECMD" ];then 8 | echo "[!] first time adding a route" 9 | ROUTECMD="ip route add default proto static scope global table loadb nexthop via $IP weight 100" 10 | eval $ROUTECMD 11 | else 12 | # delete existing route 13 | echo "[-] deleting existing routes" 14 | ROUTECMDDEL=`echo $ROUTECMD | sed 's/ip route add/ip route del/'` 15 | eval $ROUTECMDDEL 16 | echo "[+] adding $IP to route table" 17 | ROUTECMD="$ROUTECMD nexthop via $IP weight 100 " 18 | eval $ROUTECMD 19 | fi 20 | 21 | # save last ran route to file 22 | echo $ROUTECMD > .routecmd 23 | -------------------------------------------------------------------------------- /nodes/aws/configs/node_setup.bash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | sudo sysctl -w net.ipv4.ip_forward=1 3 | sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 4 | -------------------------------------------------------------------------------- /nodes/aws/del_route.bash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | IP=$1 3 | # grab last ran route cmd 4 | ROUTECMD=$(cat .routecmd) 5 | echo $ROUTECMD 6 | 7 | # is there a last used route cmd 8 | if [ -z "$ROUTECMD" ];then 9 | echo "[!] cannot find last route cmd used. Will not delete $IP from routing table" 10 | exit 0 11 | else 12 | if [[ $(ip route show table loadb | grep -o $IP) ]];then 13 | # delete existing route 14 | echo "[-] deleting existing route" 15 | ROUTECMDDEL=`echo $ROUTECMD | sed 's/ip route add/ip route del/'` 16 | echo $ROUTECMDDEL 17 | eval $ROUTECMDDEL 18 | 19 | # add route statement without specific IP 20 | echo "[+] deleting $IP from routing table" 21 | ROUTECMD=`echo $ROUTECMD | sed "s/nexthop via $IP weight 100//"` 22 | echo $ROUTECMD 23 | eval $ROUTECMD 24 | 25 | # save last ran route to file (but always save as a 'add' statement) 26 | ROUTECMD=`echo $ROUTECMD | sed 's/ip route del/ip route add/'` 27 | echo $ROUTECMD > .routecmd 28 | 29 | else 30 | echo "[!] IP is not in the route table" 31 | exit 0 32 | fi 33 | fi 34 | 35 | -------------------------------------------------------------------------------- /nodes/aws/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | shared_credentials_file = "~/.aws/credentials" 3 | region = "us-east-2" 4 | } 5 | 6 | resource "aws_instance" "exit-node" { 7 | ami = "ami-0f65671a86f061fcd" 8 | instance_type = "t2.micro" 9 | key_name = "proxycannon" 10 | vpc_security_group_ids = ["${aws_security_group.exit-node-sec-group.id}"] 11 | subnet_id = "subnet-b1a666fd" 12 | 13 | 14 | tags { 15 | Name = "exit-node" 16 | } 17 | 18 | # upload our provisioning scripts 19 | provisioner "file" { 20 | source = "${path.module}/configs/" 21 | destination = "/tmp/" 22 | 23 | connection { 24 | type = "ssh" 25 | user = "ubuntu" 26 | private_key = "${file("${var.aws_priv_key}")}" 27 | } 28 | } 29 | 30 | # execute our provisioning scripts 31 | provisioner "remote-exec" { 32 | script = "${path.module}/configs/node_setup.bash" 33 | 34 | connection { 35 | type = "ssh" 36 | user = "ubuntu" 37 | private_key = "${file("${var.aws_priv_key}")}" 38 | } 39 | } 40 | 41 | # modify our route table when we bring up an exit-node 42 | provisioner "local-exec" { 43 | command = "sudo ./add_route.bash ${aws_instance.exit-node.private_ip}" 44 | } 45 | 46 | # modify our route table when we destroy an exit-node 47 | provisioner "local-exec" { 48 | when = "destroy" 49 | command = "sudo ./del_route.bash ${aws_instance.exit-node.private_ip}" 50 | } 51 | 52 | } 53 | 54 | 55 | resource "aws_security_group" "exit-node-sec-group" { 56 | name = "exit-node-sec-group" 57 | 58 | egress { 59 | from_port = 0 60 | to_port = 0 61 | protocol = "-1" 62 | cidr_blocks = ["0.0.0.0/0"] 63 | } 64 | ingress { 65 | from_port = 0 66 | to_port = 0 67 | protocol = "-1" 68 | cidr_blocks = ["0.0.0.0/0"] 69 | } 70 | } 71 | 72 | #output "public_ip" { 73 | # value = "${aws_instance.exit-node.public_ip}" 74 | #} 75 | 76 | #output "private_ip" { 77 | # value = "${aws_instance.exit-node.private_ip}" 78 | #} 79 | 80 | #output "ssh_cmd" { 81 | # value = "\nssh -i ${var.aws_priv_key} ubuntu@${aws_instance.exit-node.public_ip}" 82 | #} 83 | 84 | -------------------------------------------------------------------------------- /nodes/aws/variables.tf: -------------------------------------------------------------------------------- 1 | variable "aws_priv_key" { 2 | default = "~/.ssh/proxycannon.pem" 3 | } 4 | -------------------------------------------------------------------------------- /setup/control-server-setup.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | cd /etc/openvpn/easy-rsa/ 3 | source ./vars 4 | /etc/openvpn/easy-rsa/pkitool --initca 5 | /etc/openvpn/easy-rsa/pkitool --server server 6 | /usr/bin/openssl dhparam -out /etc/openvpn/easy-rsa/keys/dh2048.pem 2048 7 | openvpn --genkey --secret /etc/openvpn/easy-rsa/keys/ta.key 8 | /etc/openvpn/easy-rsa/pkitool client01 9 | /etc/openvpn/easy-rsa/pkitool node01 10 | systemctl start openvpn@node-server.service 11 | systemctl start openvpn@client-server.service 12 | sysctl -w net.ipv4.ip_forward=1 13 | -------------------------------------------------------------------------------- /setup/install.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # install deps 3 | apt install unzip git-core openvpn easy-rsa 4 | 5 | # install terraform 6 | wget https://releases.hashicorp.com/terraform/0.11.10/terraform_0.11.10_linux_amd64.zip 7 | unzip terraform_0.11.10_linux_amd64.zip 8 | cp terraform /usr/bin/ 9 | 10 | # get proxycannon-ng 11 | git clone https://github.com/proxycannon/proxycannon-ng 12 | 13 | # create directory for our aws credentials 14 | mkdir ~/.aws 15 | touch ~/.aws/credentials 16 | 17 | echo "copy your aws ssh private key to ~/.ssh/proxycannon.pem and chmod 600" 18 | 19 | echo "place your aws api id and key in ~/.aws/credentials" 20 | -------------------------------------------------------------------------------- /setup/setup-load-balancing.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # enable ip forwarding 3 | echo 1 > /proc/sys/net/ipv4/ip_forward 4 | 5 | # use L4 (src ip, src dport, dest ip, dport) hashing for load balancing instead of L3 (src ip ,dst ip) 6 | echo 1 > /proc/sys/net/ipv4/fib_multipath_hash_policy 7 | 8 | # setup a second routing table 9 | echo "50 loadb" >> /etc/iproute2/rt_tables 10 | 11 | # set rule for openvpn client source network to use the second routing table 12 | ip rule add from 10.10.10.0/24 table loadb 13 | 14 | # always snat from eth0 15 | iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 16 | 17 | # setup load balanced default gws for second routing table 18 | # TODO these gw ips need to be dynamic. they are the far end of the 19 | #ip route add default proto static scope global table loadb nexthop via 172.31.41.121 weight 100 nexthop via 172.31.46.51 weight 100 20 | --------------------------------------------------------------------------------