Skip to content

Commit

Permalink
Add support for network interface selection #45
Browse files Browse the repository at this point in the history
  • Loading branch information
firefart committed Apr 23, 2024
1 parent 660e20f commit d46567c
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 7 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ All funds that are donated to this project will be donated to charity. A full lo
- automatically disable progress output when output is redirected
- fix extra special characters when run with `--no-progress`
- warn when using vhost mode with a proxy and http based urls as this might not work as expected
- add `interface` and `local-ip` parameters to specify the interface for http requests

## 3.6

Expand Down
49 changes: 49 additions & 0 deletions cli/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"crypto/tls"
"fmt"
"net"
"os"
"regexp"
"strconv"
Expand Down Expand Up @@ -31,6 +32,8 @@ func BasicHTTPOptions() []cli.Flag {
&cli.StringFlag{Name: "client-cert-pem-key", Aliases: []string{"ccpk"}, Usage: "private key in PEM format for optional TLS client certificates (this key needs to have no password)"},
&cli.StringFlag{Name: "client-cert-p12", Aliases: []string{"ccp12"}, Usage: "a p12 file to use for options TLS client certificates"},
&cli.StringFlag{Name: "client-cert-p12-password", Aliases: []string{"ccp12p"}, Usage: "the password to the p12 file"},
&cli.StringFlag{Name: "interface", Aliases: []string{"iface"}, Usage: "specify network interface to use. Can't be used with local-ip"},
&cli.StringFlag{Name: "local-ip", Usage: "specify local ip of network interface to use. Can't be used with interface"},
}
}

Expand Down Expand Up @@ -81,6 +84,27 @@ func ParseBasicHTTPOptions(c *cli.Context) (libgobuster.BasicHTTPOptions, error)
}
}

iface := c.String("interface")
localIP := c.String("local-ip")
if iface != "" && localIP != "" {
return opts, fmt.Errorf("can not set both interface and local-ip")
}

switch {
case iface != "":
a, err := getLocalAddrFromInterface(iface)
if err != nil {
return opts, err
}
opts.LocalAddr = a
case localIP != "":
a, err := net.ResolveIPAddr("ip", localIP)
if err != nil {
return opts, err
}
opts.LocalAddr = a
}

return opts, nil
}

Expand Down Expand Up @@ -238,3 +262,28 @@ func ParseGlobalOptions(c *cli.Context) (libgobuster.Options, error) {
opts.Debug = c.Bool("debug")
return opts, nil
}

func getLocalAddrFromInterface(iface string) (net.Addr, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, fmt.Errorf("could not get interfaces: %w", err)
}

for _, i := range ifaces {
if i.Name == iface {
addrs, err := i.Addrs()
if err != nil {
return nil, fmt.Errorf("could not get local addrs for iface %s: %w", i.Name, err)
}
for _, a := range addrs {
switch v := a.(type) {
case *net.IPAddr:
return v, nil
case *net.IPNet:
return v, nil
}
}
}
}
return nil, fmt.Errorf("could not find ip for interface %s", iface)
}
6 changes: 6 additions & 0 deletions gobusterdir/gobusterdir.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,12 @@ func (d *GobusterDir) GetConfigString() (string, error) {
}
}

if o.BasicHTTPOptions.LocalAddr != nil {
if _, err := fmt.Fprintf(tw, "[+] Local IP:\t%s\n", o.BasicHTTPOptions.LocalAddr); err != nil {
return "", err
}
}

if o.HideLength {
if _, err := fmt.Fprintf(tw, "[+] Show length:\tfalse\n"); err != nil {
return "", err
Expand Down
6 changes: 6 additions & 0 deletions gobusterfuzz/gobusterfuzz.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@ func (d *GobusterFuzz) GetConfigString() (string, error) {
}
}

if o.BasicHTTPOptions.LocalAddr != nil {
if _, err := fmt.Fprintf(tw, "[+] Local IP:\t%s\n", o.BasicHTTPOptions.LocalAddr); err != nil {
return "", err
}
}

if o.Username != "" {
if _, err := fmt.Fprintf(tw, "[+] Auth User:\t%s\n", o.Username); err != nil {
return "", err
Expand Down
6 changes: 6 additions & 0 deletions gobustergcs/gobustersgcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ func (s *GobusterGCS) GetConfigString() (string, error) {
}
}

if o.BasicHTTPOptions.LocalAddr != nil {
if _, err := fmt.Fprintf(tw, "[+] Local IP:\t%s\n", o.BasicHTTPOptions.LocalAddr); err != nil {
return "", err
}
}

if _, err := fmt.Fprintf(tw, "[+] Timeout:\t%s\n", o.Timeout.String()); err != nil {
return "", err
}
Expand Down
6 changes: 6 additions & 0 deletions gobusters3/gobusters3.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ func (s *GobusterS3) GetConfigString() (string, error) {
}
}

if o.BasicHTTPOptions.LocalAddr != nil {
if _, err := fmt.Fprintf(tw, "[+] Local IP:\t%s\n", o.BasicHTTPOptions.LocalAddr); err != nil {
return "", err
}
}

if _, err := fmt.Fprintf(tw, "[+] Timeout:\t%s\n", o.Timeout.String()); err != nil {
return "", err
}
Expand Down
6 changes: 6 additions & 0 deletions gobustervhost/gobustervhost.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,12 @@ func (v *GobusterVhost) GetConfigString() (string, error) {
}
}

if o.BasicHTTPOptions.LocalAddr != nil {
if _, err := fmt.Fprintf(tw, "[+] Local IP:\t%s\n", o.BasicHTTPOptions.LocalAddr); err != nil {
return "", err
}
}

if o.Username != "" {
if _, err := fmt.Fprintf(tw, "[+] Auth User:\t%s\n", o.Username); err != nil {
return "", err
Expand Down
26 changes: 20 additions & 6 deletions libgobuster/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/http"
"net/http/httputil"
"net/url"
Expand Down Expand Up @@ -79,15 +80,28 @@ func NewHTTPClient(opt *HTTPOptions, logger *Logger) (*HTTPClient, error) {
tlsConfig.Certificates = []tls.Certificate{*opt.TLSCertificate}
}

transport := &http.Transport{
Proxy: proxyURLFunc,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
TLSClientConfig: &tlsConfig,
}

// set specific network interface
if opt.LocalAddr != nil {
dialer := &net.Dialer{
Timeout: opt.Timeout,
LocalAddr: opt.LocalAddr,
}
transport.DialContext = dialer.DialContext
}

client.client = &http.Client{
Timeout: opt.Timeout,
CheckRedirect: redirectFunc,
Transport: &http.Transport{
Proxy: proxyURLFunc,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 100,
TLSClientConfig: &tlsConfig,
}}
Transport: transport,
}

client.username = opt.Username
client.password = opt.Password
client.userAgent = opt.UserAgent
Expand Down
4 changes: 3 additions & 1 deletion libgobuster/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package libgobuster

import "time"
import (
"time"
)

// Options holds all options that can be passed to libgobuster
type Options struct {
Expand Down
2 changes: 2 additions & 0 deletions libgobuster/options_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package libgobuster

import (
"crypto/tls"
"net"
"time"
)

Expand All @@ -14,6 +15,7 @@ type BasicHTTPOptions struct {
RetryOnTimeout bool
RetryAttempts int
TLSCertificate *tls.Certificate
LocalAddr net.Addr
}

// HTTPOptions is the struct to pass in all http options to Gobuster
Expand Down

0 comments on commit d46567c

Please sign in to comment.