-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 3af3fc3
Showing
6 changed files
with
449 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2016 Tom Steele | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# Fork | ||
|
||
Forked from tomsteele/cloud-proxy and repurposed to support scanning only, and maybe eventuall additional commands. | ||
|
||
# cloud-proxy | ||
cloud-proxy creates multiple DO droplets and then starts local socks proxies using SSH. After exiting, the droplets are deleted. | ||
|
||
### Warning | ||
This tool will deploy as many droplets as you desire, and will make a best effort to delete them after use. However, you are ultimately going to pay the bill for these droplets, and it is up to you, and you alone to ensure they actually get deleted. | ||
|
||
### Install | ||
Download a compiled release [here](https://github.com/tomsteele/cloud-proxy/releases/latest). You can now execute without any dependencies. Currently the only supported and tested OS is Linux: | ||
``` | ||
$ ./cloud-proxy | ||
``` | ||
### Usage | ||
``` | ||
Usage of ./cloud-proxy: | ||
-count int | ||
Amount of droplets to deploy (default 5) | ||
-force | ||
Bypass built-in protections that prevent you from deploying more than 50 droplets | ||
-key string | ||
SSH key fingerprint | ||
-key-location string | ||
SSH key location (default "~/.ssh/id_rsa") | ||
-name string | ||
Droplet name prefix (default "cloud-proxy") | ||
-regions string | ||
Comma separated list of regions to deploy droplets to, defaults to all. (default "*") | ||
-start-tcp int | ||
TCP port to start first proxy on and increment from (default 55555) | ||
-token string | ||
DO API key | ||
-v Print version and exit | ||
``` | ||
|
||
### Getting Started | ||
To use cloud-proxy you will need to have a DO API token, you can get one [here](https://cloud.digitalocean.com/settings/api/tokens). Next, ensure you have an SSH key saved on DO. This is the key that SSH will authentication with. The DO API and cloud-proxy require you to provide the fingerprint of the key you would like to use. You can obtain the fingerprint using `ssh-keygen`: | ||
``` | ||
$ ssh-keygen -lf ~/.ssh/id_rsa.pub | ||
``` | ||
|
||
If your key requires a passphrase, you will need to use ssh-agent: | ||
``` | ||
$ eval `ssh-agent -s` | ||
$ ssh-add ~/.ssh/id_rsa | ||
``` | ||
|
||
Now you may create some proxies: | ||
``` | ||
$ cloud-proxy -count 2 -token <api-token> -key <fingerprint> | ||
``` | ||
|
||
When you are finished using your proxies, use CTRL-C to interrupt the program, cloud-proxy will catch the interrupt and delete the droplets. | ||
|
||
cloud-proxy will output a proxy list for proxychains and [socksd](https://github.com/eahydra/socks/tree/master/cmd/socksd). proxychains can be configured to iterate over a random proxy for each connection by uncommenting `random_chain`, you should also comment out `string-chain`, which is the default. You will also need to uncomment `chain_len` and set it to `1`. | ||
|
||
socksd can be helpful for programs that can accept a socks proxy, but may not work nicely with proxychains. socksd will listen as a socks proxy, and can be configured to use a set of upstream proxies, which it will iterate through in a round-robin manner. Follow the instructions in the README linked above, as it is self explanitory. | ||
|
||
### Example Output | ||
``` | ||
$ ./cloud-proxy -token <my_token> -key <my_fingerprint> | ||
==> Info: Droplets deployed. Waiting 100 seconds... | ||
==> Info: SSH proxy started on port 55555 on droplet name: cloud-proxy-1 IP: <IP> | ||
==> Info: SSH proxy started on port 55556 on droplet name: cloud-proxy-2 IP: <IP> | ||
==> Info: SSH proxy started on port 55557 on droplet name: cloud-proxy-3 IP: <IP> | ||
==> Info: SSH proxy started on port 55558 on droplet name: cloud-proxy-4 IP: <IP> | ||
==> Info: SSH proxy started on port 55559 on droplet name: cloud-proxy-5 IP: <IP> | ||
==> Info: proxychains config | ||
socks5 127.0.0.1 55555 | ||
socks5 127.0.0.1 55556 | ||
socks5 127.0.0.1 55557 | ||
socks5 127.0.0.1 55558 | ||
socks5 127.0.0.1 55559 | ||
==> Info: socksd config | ||
"upstreams": [ | ||
{"type": "socks5", "address": "127.0.0.1:55555"}, | ||
{"type": "socks5", "address": "127.0.0.1:55556"}, | ||
{"type": "socks5", "address": "127.0.0.1:55557"}, | ||
{"type": "socks5", "address": "127.0.0.1:55558"}, | ||
{"type": "socks5", "address": "127.0.0.1:55559"} | ||
] | ||
==> Info: Please CTRL-C to destroy droplets | ||
^C==> Info: Deleted droplet name: cloud-proxy-1 | ||
==> Info: Deleted droplet name: cloud-proxy-2 | ||
==> Info: Deleted droplet name: cloud-proxy-3 | ||
==> Info: Deleted droplet name: cloud-proxy-4 | ||
==> Info: Deleted droplet name: cloud-proxy-5 | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/digitalocean/godo" | ||
"github.com/jmcvetta/randutil" | ||
) | ||
|
||
func doRegions(client *godo.Client) ([]string, error) { | ||
slugs := []string{} | ||
regions, _, err := client.Regions.List(&godo.ListOptions{}) | ||
if err != nil { | ||
return slugs, err | ||
} | ||
for _, r := range regions { | ||
slugs = append(slugs, r.Slug) | ||
} | ||
return slugs, nil | ||
} | ||
|
||
func newDropLetMultiCreateRequest(prefix, region, keyID string, count int) *godo.DropletMultiCreateRequest { | ||
|
||
names := []string{} | ||
for i := 0; i < count; i++ { | ||
name, _ := randutil.AlphaString(8) | ||
names = append(names, fmt.Sprintf("%s-%s", prefix, name)) | ||
} | ||
|
||
return &godo.DropletMultiCreateRequest{ | ||
Names: names, | ||
Region: region, | ||
Size: "512mb", | ||
Image: godo.DropletCreateImage{ | ||
Slug: "ubuntu-14-04-x64", | ||
}, | ||
SSHKeys: []godo.DropletCreateSSHKey{ | ||
godo.DropletCreateSSHKey{ | ||
Fingerprint: keyID, | ||
}, | ||
}, | ||
Backups: false, | ||
IPv6: false, | ||
PrivateNetworking: false, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"os/exec" | ||
|
||
"github.com/digitalocean/godo" | ||
) | ||
|
||
// Machine is just a wrapper around a created droplet. | ||
type Machine struct { | ||
ID int | ||
Name string | ||
IPv4 string | ||
SSHActive bool | ||
Stderr *bufio.Reader | ||
Listener string | ||
CMD *exec.Cmd | ||
} | ||
|
||
// IsReady ensures that the machine has an IP address. | ||
func (m *Machine) IsReady() bool { | ||
return m.IPv4 != "" | ||
} | ||
|
||
// GetIPs populates the IPv4 address of the machine. | ||
func (m *Machine) GetIPs(client *godo.Client) error { | ||
droplet, _, err := client.Droplets.Get(m.ID) | ||
if err != nil { | ||
return err | ||
} | ||
m.IPv4, err = droplet.PublicIPv4() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
// StartSSHProxy starts a socks proxy on 127.0.0.1 or the desired port. | ||
func (m *Machine) StartSSHProxy(port, sshKeyLocation string) error { | ||
m.Listener = port | ||
m.CMD = exec.Command("ssh", "-N", "-D", port, "-o", "StrictHostKeyChecking=no", "-i", sshKeyLocation, fmt.Sprintf("root@%s", m.GetIP())) | ||
stderr, err := m.CMD.StderrPipe() | ||
if err != nil { | ||
return err | ||
} | ||
m.Stderr = bufio.NewReader(stderr) | ||
if err := m.CMD.Start(); err != nil { | ||
return err | ||
} | ||
m.SSHActive = true | ||
return nil | ||
} | ||
|
||
// Destroy deletes the droplet. | ||
func (m *Machine) Destroy(client *godo.Client) error { | ||
_, err := client.Droplets.Delete(m.ID) | ||
return err | ||
} | ||
|
||
// GetIP returns the IPv4 address. | ||
func (m *Machine) GetIP() string { | ||
return m.IPv4 | ||
} | ||
|
||
func dropletsToMachines(droplets []godo.Droplet) []Machine { | ||
m := []Machine{} | ||
for _, d := range droplets { | ||
m = append(m, Machine{ | ||
ID: d.ID, | ||
Name: d.Name, | ||
}) | ||
} | ||
return m | ||
} | ||
|
||
// PrintStdError reads from stderr from ssh and prints it to stdout. | ||
func (m *Machine) PrintStdError() { | ||
for { | ||
str, err := m.Stderr.ReadString('\n') | ||
if err != nil && str != "" { | ||
fmt.Printf("From %s SSH stderr\n", m.Name) | ||
fmt.Println(str) | ||
} | ||
} | ||
|
||
} | ||
|
||
func printProxyChains(machines []Machine) { | ||
for _, m := range machines { | ||
fmt.Printf("socks5 127.0.0.1 %s\n", m.Listener) | ||
} | ||
} | ||
|
||
func printSocksd(machines []Machine) { | ||
fmt.Printf("\"upstreams\": [\n") | ||
for i, m := range machines { | ||
fmt.Printf("{\"type\": \"socks5\", \"address\": \"127.0.0.1:%s\"}", m.Listener) | ||
if i < len(machines)-1 { | ||
fmt.Printf(",\n") | ||
} | ||
} | ||
fmt.Printf("\n]\n") | ||
} |
Oops, something went wrong.