mirror of https://github.com/daffainfo/nuclei.git
add option to specify network interface (#2384)
* add option to specify network interface * add source-ip flag * fix typo * fix err return * readme update Co-authored-by: Sandeep Singh <sandeep@projectdiscovery.io>dev
parent
30054d1fb6
commit
011da1388d
|
@ -142,6 +142,7 @@ OUTPUT:
|
||||||
|
|
||||||
CONFIGURATIONS:
|
CONFIGURATIONS:
|
||||||
-config string path to the nuclei configuration file
|
-config string path to the nuclei configuration file
|
||||||
|
-config-directory string override the default config path ($home/.config)
|
||||||
-fr, -follow-redirects enable following redirects for http templates
|
-fr, -follow-redirects enable following redirects for http templates
|
||||||
-mr, -max-redirects int max number of redirects to follow for http templates (default 10)
|
-mr, -max-redirects int max number of redirects to follow for http templates (default 10)
|
||||||
-dr, -disable-redirects disable redirects for http templates
|
-dr, -disable-redirects disable redirects for http templates
|
||||||
|
@ -158,6 +159,8 @@ CONFIGURATIONS:
|
||||||
-sml, -show-match-line show match lines for file templates, works with extractors only
|
-sml, -show-match-line show match lines for file templates, works with extractors only
|
||||||
-ztls use ztls library with autofallback to standard one for tls13
|
-ztls use ztls library with autofallback to standard one for tls13
|
||||||
-sni string tls sni hostname to use (default: input domain name)
|
-sni string tls sni hostname to use (default: input domain name)
|
||||||
|
-i, -interface string network interface to use for network scan
|
||||||
|
-sip, -source-ip string source ip address to use for network scan
|
||||||
|
|
||||||
INTERACTSH:
|
INTERACTSH:
|
||||||
-iserver, -interactsh-server string interactsh server url for self-hosted instance (default: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
-iserver, -interactsh-server string interactsh server url for self-hosted instance (default: oast.pro,oast.live,oast.site,oast.online,oast.fun,oast.me)
|
||||||
|
|
|
@ -183,6 +183,8 @@ on extensive configurability, massive extensibility and ease of use.`)
|
||||||
flagSet.BoolVarP(&options.ShowMatchLine, "show-match-line", "sml", false, "show match lines for file templates, works with extractors only"),
|
flagSet.BoolVarP(&options.ShowMatchLine, "show-match-line", "sml", false, "show match lines for file templates, works with extractors only"),
|
||||||
flagSet.BoolVar(&options.ZTLS, "ztls", false, "use ztls library with autofallback to standard one for tls13"),
|
flagSet.BoolVar(&options.ZTLS, "ztls", false, "use ztls library with autofallback to standard one for tls13"),
|
||||||
flagSet.StringVar(&options.SNI, "sni", "", "tls sni hostname to use (default: input domain name)"),
|
flagSet.StringVar(&options.SNI, "sni", "", "tls sni hostname to use (default: input domain name)"),
|
||||||
|
flagSet.StringVarP(&options.Interface, "interface", "i", "", "network interface to use for network scan"),
|
||||||
|
flagSet.StringVarP(&options.SourceIP, "source-ip", "sip", "", "source ip address to use for network scan"),
|
||||||
flagSet.StringVar(&options.CustomConfigDir, "config-directory", "", "Override the default config path ($home/.config)"),
|
flagSet.StringVar(&options.CustomConfigDir, "config-directory", "", "Override the default config path ($home/.config)"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package protocolstate
|
package protocolstate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/projectdiscovery/fastdialer/fastdialer"
|
"github.com/projectdiscovery/fastdialer/fastdialer"
|
||||||
|
@ -16,6 +19,48 @@ func Init(options *types.Options) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
opts := fastdialer.DefaultOptions
|
opts := fastdialer.DefaultOptions
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case options.SourceIP != "" && options.Interface != "":
|
||||||
|
isAssociated, err := isIpAssociatedWithInterface(options.SourceIP, options.Interface)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isAssociated {
|
||||||
|
opts.Dialer = &net.Dialer{
|
||||||
|
LocalAddr: &net.TCPAddr{
|
||||||
|
IP: net.ParseIP(options.SourceIP),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("source ip (%s) is not associated with the interface (%s)", options.SourceIP, options.Interface)
|
||||||
|
}
|
||||||
|
case options.SourceIP != "":
|
||||||
|
isAssociated, err := isIpAssociatedWithInterface(options.SourceIP, "any")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isAssociated {
|
||||||
|
opts.Dialer = &net.Dialer{
|
||||||
|
LocalAddr: &net.TCPAddr{
|
||||||
|
IP: net.ParseIP(options.SourceIP),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("source ip (%s) is not associated with any network interface", options.SourceIP)
|
||||||
|
}
|
||||||
|
case options.Interface != "":
|
||||||
|
ifadrr, err := interfaceAddress(options.Interface)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
opts.Dialer = &net.Dialer{
|
||||||
|
LocalAddr: &net.TCPAddr{
|
||||||
|
IP: ifadrr,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if options.SystemResolvers {
|
if options.SystemResolvers {
|
||||||
opts.EnableFallback = true
|
opts.EnableFallback = true
|
||||||
}
|
}
|
||||||
|
@ -33,6 +78,58 @@ func Init(options *types.Options) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isIpAssociatedWithInterface checks if the given IP is associated with the given interface.
|
||||||
|
func isIpAssociatedWithInterface(souceIP, interfaceName string) (bool, error) {
|
||||||
|
addrs, err := interfaceAddresses(interfaceName)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok {
|
||||||
|
if ipnet.IP.String() == souceIP {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// interfaceAddress returns the first IPv4 address of the given interface.
|
||||||
|
func interfaceAddress(interfaceName string) (net.IP, error) {
|
||||||
|
addrs, err := interfaceAddresses(interfaceName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var address net.IP
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
||||||
|
if ipnet.IP.To4() != nil {
|
||||||
|
address = ipnet.IP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if address == nil {
|
||||||
|
return nil, fmt.Errorf("no suitable address found for interface: `%s`", interfaceName)
|
||||||
|
}
|
||||||
|
return address, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// interfaceAddresses returns all interface addresses.
|
||||||
|
func interfaceAddresses(interfaceName string) ([]net.Addr, error) {
|
||||||
|
if interfaceName == "any" {
|
||||||
|
return net.InterfaceAddrs()
|
||||||
|
}
|
||||||
|
ief, err := net.InterfaceByName(interfaceName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to get interface: `%s`", interfaceName)
|
||||||
|
}
|
||||||
|
addrs, err := ief.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to get interface addresses for: `%s`", interfaceName)
|
||||||
|
}
|
||||||
|
return addrs, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the global shared fastdialer
|
// Close closes the global shared fastdialer
|
||||||
func Close() {
|
func Close() {
|
||||||
if Dialer != nil {
|
if Dialer != nil {
|
||||||
|
|
|
@ -230,6 +230,10 @@ type Options struct {
|
||||||
DisableRedirects bool
|
DisableRedirects bool
|
||||||
// SNI custom hostname
|
// SNI custom hostname
|
||||||
SNI string
|
SNI string
|
||||||
|
// Interface to use for network scan
|
||||||
|
Interface string
|
||||||
|
// SourceIP sets custom source IP address for network requests
|
||||||
|
SourceIP string
|
||||||
// Health Check
|
// Health Check
|
||||||
HealthCheck bool
|
HealthCheck bool
|
||||||
// Time to wait between each input read operation before closing the stream
|
// Time to wait between each input read operation before closing the stream
|
||||||
|
|
Loading…
Reference in New Issue