Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<a href="https://discord.gg/projectdiscovery">Join Discord</a>
</p>

Swiss Army Knife Proxy for rapid deployments. Supports multiple operations such as request/response dump, filtering and manipulation via DSL language, upstream HTTP/Socks5 proxy.
Swiss Army Knife Proxy for rapid deployments. Supports multiple operations such as request/response dump, filtering and manipulation via DSL language, upstream HTTP/SOCKS5 proxy.
Additionally, a replay utility allows to import the dumped traffic (request/responses with correct domain name) into BurpSuite or any other proxy by simply setting the upstream proxy to proxify.

# Features
Expand Down Expand Up @@ -60,7 +60,7 @@ proxify -h
This will display help for the tool. Here are all the switches it supports.

```console
Swiss Army Knife Proxy for rapid deployments. Supports multiple operations such as request/response dump,filtering and manipulation via DSL language, upstream HTTP/Socks5 proxy
Swiss Army Knife Proxy for rapid deployments. Supports multiple operations such as request/response dump,filtering and manipulation via DSL language, upstream HTTP/SOCKS5 proxy

Usage:
./proxify [flags]
Expand Down
10 changes: 5 additions & 5 deletions internal/runner/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type Options struct {
Verbosity types.Verbosity
Version bool
ListenAddrHTTP string
ListenAddrSocks5 string
ListenAddrSOCKS5 string
ListenDNSAddr string
DNSMapping string // DNSMapping contains user provided hosts
DNSFallbackResolver string // Listen DNS Ip and port (ip:port)
Expand All @@ -47,7 +47,7 @@ type Options struct {
ResponseDSL goflags.StringSlice // Response Filter DSL
ResponseMatchReplaceDSL goflags.StringSlice // Request Match-Replace DSL
UpstreamHTTPProxies goflags.StringSlice // Upstream HTTP comma separated Proxies (e.g. http://proxyip:proxyport)
UpstreamSocks5Proxies goflags.StringSlice // Upstream SOCKS5 comma separated Proxies (e.g. socks5://proxyip:proxyport)
UpstreamSOCKS5Proxies goflags.StringSlice // Upstream SOCKS5 comma separated Proxies (e.g. socks5://proxyip:proxyport)
UpstreamProxyRequestsNumber int // Number of requests before switching upstream proxy
DumpRequest bool // Dump requests in separate files
DumpResponse bool // Dump responses in separate files
Expand All @@ -71,7 +71,7 @@ func ParseOptions() (*Options, error) {
options := &Options{}

flagSet := goflags.NewFlagSet()
flagSet.SetDescription(`Swiss Army Knife Proxy for rapid deployments. Supports multiple operations such as request/response dump,filtering and manipulation via DSL language, upstream HTTP/Socks5 proxy`)
flagSet.SetDescription(`Swiss Army Knife Proxy for rapid deployments. Supports multiple operations such as request/response dump,filtering and manipulation via DSL language, upstream HTTP/SOCKS5 proxy`)

flagSet.CreateGroup("output", "Output",
// Todo: flagSet.BoolVar(&options.Dump, "dump", true, "Dump HTTP requests/response to output file"),
Expand All @@ -98,15 +98,15 @@ func ParseOptions() (*Options, error) {

flagSet.CreateGroup("network", "Network",
flagSet.StringVarP(&options.ListenAddrHTTP, "http-addr", "ha", "127.0.0.1:8888", "Listening HTTP IP and Port address (ip:port)"),
flagSet.StringVarP(&options.ListenAddrSocks5, "socks-addr", "sa", "127.0.0.1:10080", "Listening SOCKS IP and Port address (ip:port)"),
flagSet.StringVarP(&options.ListenAddrSOCKS5, "socks-addr", "sa", "127.0.0.1:10080", "Listening SOCKS IP and Port address (ip:port)"),
flagSet.StringVarP(&options.ListenDNSAddr, "dns-addr", "da", "", "Listening DNS IP and Port address (ip:port)"),
flagSet.StringVarP(&options.DNSMapping, "dns-mapping", "dm", "", "Domain to IP DNS mapping (eg domain:ip,domain:ip,..)"),
flagSet.StringVarP(&options.DNSFallbackResolver, "resolver", "r", "", "Custom DNS resolvers to use (ip:port)"),
)

flagSet.CreateGroup("proxy", "Proxy",
flagSet.StringSliceVarP(&options.UpstreamHTTPProxies, "http-proxy", "hp", nil, "Upstream HTTP Proxies (eg http://proxy-ip:proxy-port)", goflags.NormalizedStringSliceOptions),
flagSet.StringSliceVarP(&options.UpstreamSocks5Proxies, "socks5-proxy", "sp", nil, "Upstream SOCKS5 Proxies (eg socks5://proxy-ip:proxy-port)", goflags.NormalizedStringSliceOptions),
flagSet.StringSliceVarP(&options.UpstreamSOCKS5Proxies, "socks5-proxy", "sp", nil, "Upstream SOCKS5 Proxies (eg socks5://proxy-ip:proxy-port)", goflags.NormalizedStringSliceOptions),
flagSet.IntVar(&options.UpstreamProxyRequestsNumber, "c", 1, "Number of requests before switching to the next upstream proxy"),
)

Expand Down
12 changes: 6 additions & 6 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ func NewRunner(options *Options) (*Runner, error) {
CertCacheSize: options.CertCacheSize,
Verbosity: options.Verbosity,
ListenAddrHTTP: options.ListenAddrHTTP,
ListenAddrSocks5: options.ListenAddrSocks5,
ListenAddrSOCKS5: options.ListenAddrSOCKS5,
OutputFile: options.OutputFile,
OutputFormat: options.OutputFormat,
OutputDirectory: options.OutputDirectory,
OutputHar: options.OutputHar,
RequestDSL: options.RequestDSL,
ResponseDSL: options.ResponseDSL,
UpstreamHTTPProxies: options.UpstreamHTTPProxies,
UpstreamSock5Proxies: options.UpstreamSocks5Proxies,
UpstreamSOCKS5Proxies: options.UpstreamSOCKS5Proxies,
ListenDNSAddr: options.ListenDNSAddr,
DNSMapping: options.DNSMapping,
DNSFallbackResolver: options.DNSFallbackResolver,
Expand Down Expand Up @@ -91,8 +91,8 @@ func (r *Runner) Run() error {
if r.options.ListenAddrHTTP != "" {
gologger.Info().Msgf("HTTP Proxy Listening on %s\n", r.options.ListenAddrHTTP)
}
if r.options.ListenAddrSocks5 != "" {
gologger.Info().Msgf("Socks5 Proxy Listening on %s\n", r.options.ListenAddrSocks5)
if r.options.ListenAddrSOCKS5 != "" {
gologger.Info().Msgf("SOCKS5 Proxy Listening on %s\n", r.options.ListenAddrSOCKS5)
}

if r.options.OutputFile != "" {
Expand All @@ -112,8 +112,8 @@ func (r *Runner) Run() error {

if len(r.options.UpstreamHTTPProxies) > 0 {
gologger.Info().Msgf("Using upstream HTTP proxies: %s\n", r.options.UpstreamHTTPProxies)
} else if len(r.options.UpstreamSocks5Proxies) > 0 {
gologger.Info().Msgf("Using upstream SOCKS5 proxies: %s\n", r.options.UpstreamSocks5Proxies)
} else if len(r.options.UpstreamSOCKS5Proxies) > 0 {
gologger.Info().Msgf("Using upstream SOCKS5 proxies: %s\n", r.options.UpstreamSOCKS5Proxies)
}

if r.options.DNSMapping != "" {
Expand Down
76 changes: 38 additions & 38 deletions proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ type Options struct {
CertCacheSize int
Directory string
ListenAddrHTTP string
ListenAddrSocks5 string
ListenAddrSOCKS5 string
OutputDirectory string
OutputFile string
OutputFormat string
OutputHar string
RequestDSL []string
ResponseDSL []string
UpstreamHTTPProxies []string
UpstreamSock5Proxies []string
UpstreamSOCKS5Proxies []string
ListenDNSAddr string
DNSMapping string
DNSFallbackResolver string
Expand All @@ -81,12 +81,12 @@ type Proxy struct {
options *Options
logger *logger.Logger
httpProxy *martian.Proxy
socks5proxy *socks5.Server
socks5tunnel *superproxy.SuperProxy
socks5Proxy *socks5.Server
socks5Tunnel *superproxy.SuperProxy
bufioPool *bufiopool.Pool
tinydns *tinydns.TinyDNS
rbhttp *rbtransport.RoundTransport
rbsocks5 *rbtransport.RoundTransport
tinyDNS *tinydns.TinyDNS
rbHTTP *rbtransport.RoundTransport
rbSOCKS5 *rbtransport.RoundTransport
proxifyMux *http.ServeMux // serve banner page and static files
listenAddr string
}
Expand Down Expand Up @@ -117,27 +117,27 @@ func NewProxy(options *Options) (*Proxy, error) {
Kafka: options.Kafka,
})

var tdns *tinydns.TinyDNS
var tDNS *tinydns.TinyDNS

fastdialerOptions := fastdialer.DefaultOptions
fastdialerOptions.EnableFallback = true
fastdialerOptions.Deny = options.Deny
fastdialerOptions.Allow = options.Allow
if options.ListenDNSAddr != "" {
dnsmapping := make(map[string]*tinydns.DnsRecord)
dnsMapping := make(map[string]*tinydns.DnsRecord)
for _, record := range strings.Split(options.DNSMapping, ",") {
data := strings.Split(record, ":")
if len(data) != 2 {
continue
}
dnsmapping[data[0]] = &tinydns.DnsRecord{A: []string{data[1]}}
dnsMapping[data[0]] = &tinydns.DnsRecord{A: []string{data[1]}}
}
var err error
tdns, err = tinydns.New(&tinydns.Options{
tDNS, err = tinydns.New(&tinydns.Options{
ListenAddress: options.ListenDNSAddr,
Net: "udp",
UpstreamServers: []string{options.DNSFallbackResolver},
DnsRecords: dnsmapping,
DnsRecords: dnsMapping,
})
if err != nil {
return nil, err
Expand All @@ -149,20 +149,20 @@ func NewProxy(options *Options) (*Proxy, error) {
return nil, err
}

var rbhttp, rbsocks5 *rbtransport.RoundTransport
var rbHTTP, rbSOCKS5 *rbtransport.RoundTransport
if len(options.UpstreamHTTPProxies) > 0 {
rbhttp, err = rbtransport.NewWithOptions(options.UpstreamProxyRequestsNumber, options.UpstreamHTTPProxies...)
rbHTTP, err = rbtransport.NewWithOptions(options.UpstreamProxyRequestsNumber, options.UpstreamHTTPProxies...)
if err != nil {
return nil, err
}
}
if len(options.UpstreamSock5Proxies) > 0 {
rbsocks5, err = rbtransport.NewWithOptions(options.UpstreamProxyRequestsNumber, options.UpstreamSock5Proxies...)
if len(options.UpstreamSOCKS5Proxies) > 0 {
rbSOCKS5, err = rbtransport.NewWithOptions(options.UpstreamProxyRequestsNumber, options.UpstreamSOCKS5Proxies...)
if err != nil {
return nil, err
}
}
pmux, err := getProxifyServerMux()
pMux, err := getProxifyServerMux()
if err != nil {
return nil, err
}
Expand All @@ -171,31 +171,31 @@ func NewProxy(options *Options) (*Proxy, error) {
logger: logger,
options: options,
Dialer: dialer,
tinydns: tdns,
rbhttp: rbhttp,
rbsocks5: rbsocks5,
proxifyMux: pmux,
tinyDNS: tDNS,
rbHTTP: rbHTTP,
rbSOCKS5: rbSOCKS5,
proxifyMux: pMux,
}

if err := proxy.setupHTTPProxy(); err != nil {
return nil, err
}

var socks5proxy *socks5.Server
if options.ListenAddrSocks5 != "" {
var socks5Proxy *socks5.Server
if options.ListenAddrSOCKS5 != "" {
if options.Verbosity <= types.VerbositySilent {
socks5proxy = socks5.NewServer(
socks5Proxy = socks5.NewServer(
socks5.WithLogger(socks5.NewLogger(log.New(io.Discard, "", log.Ltime|log.Lshortfile))),
socks5.WithDial(proxy.httpTunnelDialer),
)
} else {
socks5proxy = socks5.NewServer(
socks5Proxy = socks5.NewServer(
socks5.WithDial(proxy.httpTunnelDialer),
)
}
}

proxy.socks5proxy = socks5proxy
proxy.socks5Proxy = socks5Proxy

return proxy, nil
}
Expand Down Expand Up @@ -404,11 +404,11 @@ func (p *Proxy) MatchReplaceResponse(resp *http.Response) error {
func (p *Proxy) Run() error {
var wg sync.WaitGroup

if p.tinydns != nil {
if p.tinyDNS != nil {
wg.Add(1)
go func() {
defer wg.Done()
if err := p.tinydns.Run(); err != nil {
if err := p.tinyDNS.Run(); err != nil {
gologger.Warning().Msgf("Could not start dns server: %s\n", err)
}
}()
Expand Down Expand Up @@ -437,7 +437,7 @@ func (p *Proxy) Run() error {
}

// socks5 proxy
if p.socks5proxy != nil {
if p.socks5Proxy != nil {
if p.httpProxy != nil {
httpProxyIP, httpProxyPort, err := net.SplitHostPort(p.options.ListenAddrHTTP)
if err != nil {
Expand All @@ -447,7 +447,7 @@ func (p *Proxy) Run() error {
if err != nil {
return err
}
p.socks5tunnel, err = superproxy.NewSuperProxy(httpProxyIP, uint16(httpProxyPortUint), superproxy.ProxyTypeHTTP, "", "", "")
p.socks5Tunnel, err = superproxy.NewSuperProxy(httpProxyIP, uint16(httpProxyPortUint), superproxy.ProxyTypeHTTP, "", "", "")
if err != nil {
return err
}
Expand All @@ -458,7 +458,7 @@ func (p *Proxy) Run() error {
go func() {
defer wg.Done()

gologger.Fatal().Msgf("%v", p.socks5proxy.ListenAndServe("tcp", p.options.ListenAddrSocks5))
gologger.Fatal().Msgf("%v", p.socks5Proxy.ListenAndServe("tcp", p.options.ListenAddrSOCKS5))
}()
}

Expand Down Expand Up @@ -504,21 +504,21 @@ func (p *Proxy) getRoundTripper() (http.RoundTripper, error) {

if len(p.options.UpstreamHTTPProxies) > 0 {
roundtrip = &http.Transport{Proxy: func(req *http.Request) (*url.URL, error) {
return url.Parse(p.rbhttp.Next())
return url.Parse(p.rbHTTP.Next())
}, TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
} else if len(p.options.UpstreamSock5Proxies) > 0 {
} else if len(p.options.UpstreamSOCKS5Proxies) > 0 {
// for each socks5 proxy create a dialer
socks5Dialers := make(map[string]proxy.Dialer)
for _, socks5proxy := range p.options.UpstreamSock5Proxies {
dialer, err := proxy.SOCKS5("tcp", socks5proxy, nil, proxy.Direct)
for _, socks5Proxy := range p.options.UpstreamSOCKS5Proxies {
dialer, err := proxy.SOCKS5("tcp", socks5Proxy, nil, proxy.Direct)
if err != nil {
return nil, err
}
socks5Dialers[socks5proxy] = dialer
socks5Dialers[socks5Proxy] = dialer
}
roundtrip = &http.Transport{Dial: func(network, addr string) (net.Conn, error) {
// lookup next dialer
socks5Proxy := p.rbsocks5.Next()
socks5Proxy := p.rbSOCKS5.Next()
socks5Dialer := socks5Dialers[socks5Proxy]
// use it to perform the request
return socks5Dialer.Dial(network, addr)
Expand All @@ -528,7 +528,7 @@ func (p *Proxy) getRoundTripper() (http.RoundTripper, error) {
}

func (p *Proxy) httpTunnelDialer(ctx context.Context, network, addr string) (net.Conn, error) {
return p.socks5tunnel.MakeTunnel(nil, nil, p.bufioPool, addr)
return p.socks5Tunnel.MakeTunnel(nil, nil, p.bufioPool, addr)
}

func (p *Proxy) hijackNServe(req *http.Request, ctx *martian.Context) error {
Expand Down
2 changes: 1 addition & 1 deletion static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
<div class="center-text">
Swiss Army Knife Proxy for rapid deployments. <br>
Supports multiple operations such as request/response dump,<br>
filtering and manipulation via DSL language, upstream HTTP/Socks5 proxy.<br>
filtering and manipulation via DSL language, upstream HTTP/SOCKS5 proxy.<br>
Additionally, a replay utility allows to import the dumped traffic <br>
(request/responses with correct domain name) into BurpSuite or <br>
any other proxy by simply setting the upstream proxy to proxify.
Expand Down
Loading