@@ -34,6 +34,7 @@ import (
3434 "github.com/google/uuid"
3535 "github.com/rs/zerolog"
3636 "github.com/shadowy-pycoder/colors"
37+ "github.com/shadowy-pycoder/mshark/arpspoof"
3738 "github.com/shadowy-pycoder/mshark/layers"
3839 "golang.org/x/net/proxy"
3940)
6667 credsPattern = regexp .MustCompile (
6768 `(?i)(?:"|')?(username|user|login|email|password|pass|pwd)(?:"|')?\s*[:=]\s*(?:"|')?([^\s"'&]+)` ,
6869 )
70+ macPattern = regexp .MustCompile (`(?i)([a-z0-9_]+_[0-9a-f]{2}(?::[0-9a-f]{2}){2}|(?:[0-9a-f]{2}[:-]){5}[0-9a-f]{2})` )
6971)
7072
7173// Hop-by-hop headers
@@ -97,7 +99,7 @@ type Config struct {
9799 TProxyMode string
98100 Auto bool
99101 Mark uint
100- ARP bool
102+ ARPSpoof string
101103 LogFilePath string
102104 Debug bool
103105 JSON bool
@@ -121,7 +123,7 @@ type proxyapp struct {
121123 tproxyMode string
122124 auto bool
123125 mark uint
124- arp bool
126+ arpspoofer * arpspoof. ARPSpoofer
125127 user string
126128 pass string
127129 proxychain chain
@@ -1396,52 +1398,48 @@ func (p *proxyapp) applyRedirectRules() string {
13961398 cmdForward .Stdout = os .Stdout
13971399 cmdForward .Stderr = os .Stderr
13981400 _ = cmdForward .Run ()
1399- if p .arp {
1400- cmdClear := exec .Command ("bash" , "-c" , `
1401- set -ex
1402- iptables -t filter -F GOHPTS 2>/dev/null || true
1403- iptables -t filter -D FORWARD -j GOHPTS 2>/dev/null || true
1404- iptables -t filter -X GOHPTS 2>/dev/null || true
1405- ` )
1406- cmdClear .Stdout = os .Stdout
1407- cmdClear .Stderr = os .Stderr
1408- if err := cmdClear .Run (); err != nil {
1409- p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1410- }
1411- iface , err := getDefaultInterface ()
1412- if err != nil {
1413- p .logger .Fatal ().Err (err ).Msg ("failed getting default network interface" )
1414- }
1415- cmdForward := exec .Command ("bash" , "-c" , fmt .Sprintf (`
1416- set -ex
1417- iptables -t filter -N GOHPTS 2>/dev/null
1418- iptables -t filter -F GOHPTS
1419- iptables -t filter -A FORWARD -j GOHPTS
1420- iptables -t filter -A GOHPTS -i %s -j ACCEPT
1421- iptables -t filter -A GOHPTS -o %s -j ACCEPT
1422- ` , iface .Name , iface .Name ))
1423- cmdForward .Stdout = os .Stdout
1424- cmdForward .Stderr = os .Stderr
1425- if err := cmdForward .Run (); err != nil {
1426- p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1427- }
1401+ cmdClearForward := exec .Command ("bash" , "-c" , `
1402+ set -ex
1403+ iptables -t filter -F GOHPTS 2>/dev/null || true
1404+ iptables -t filter -D FORWARD -j GOHPTS 2>/dev/null || true
1405+ iptables -t filter -X GOHPTS 2>/dev/null || true
1406+ ` )
1407+ cmdClearForward .Stdout = os .Stdout
1408+ cmdClearForward .Stderr = os .Stderr
1409+ if err := cmdClearForward .Run (); err != nil {
1410+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1411+ }
1412+ iface , err := getDefaultInterface ()
1413+ if err != nil {
1414+ p .logger .Fatal ().Err (err ).Msg ("failed getting default network interface" )
1415+ }
1416+ cmdForwardFilter := exec .Command ("bash" , "-c" , fmt .Sprintf (`
1417+ set -ex
1418+ iptables -t filter -N GOHPTS 2>/dev/null
1419+ iptables -t filter -F GOHPTS
1420+ iptables -t filter -A FORWARD -j GOHPTS
1421+ iptables -t filter -A GOHPTS -i %s -j ACCEPT
1422+ iptables -t filter -A GOHPTS -o %s -j ACCEPT
1423+ ` , iface .Name , iface .Name ))
1424+ cmdForwardFilter .Stdout = os .Stdout
1425+ cmdForwardFilter .Stderr = os .Stderr
1426+ if err := cmdForwardFilter .Run (); err != nil {
1427+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
14281428 }
14291429 return string (output )
14301430}
14311431
14321432func (p * proxyapp ) clearRedirectRules (output string ) error {
1433- if p .arp {
1434- cmdClear := exec .Command ("bash" , "-c" , `
1435- set -ex
1436- iptables -t filter -F GOHPTS 2>/dev/null || true
1437- iptables -t filter -D FORWARD -j GOHPTS 2>/dev/null || true
1438- iptables -t filter -X GOHPTS 2>/dev/null || true
1439- ` )
1440- cmdClear .Stdout = os .Stdout
1441- cmdClear .Stderr = os .Stderr
1442- if err := cmdClear .Run (); err != nil {
1443- p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1444- }
1433+ cmdClear := exec .Command ("bash" , "-c" , `
1434+ set -ex
1435+ iptables -t filter -F GOHPTS 2>/dev/null || true
1436+ iptables -t filter -D FORWARD -j GOHPTS 2>/dev/null || true
1437+ iptables -t filter -X GOHPTS 2>/dev/null || true
1438+ ` )
1439+ cmdClear .Stdout = os .Stdout
1440+ cmdClear .Stderr = os .Stderr
1441+ if err := cmdClear .Run (); err != nil {
1442+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
14451443 }
14461444 var cmd * exec.Cmd
14471445 switch p .tproxyMode {
@@ -1481,6 +1479,9 @@ func (p *proxyapp) Run() {
14811479 quit := make (chan os.Signal , 1 )
14821480 p .closeConn = make (chan bool )
14831481 signal .Notify (quit , os .Interrupt )
1482+ if p .arpspoofer != nil {
1483+ go p .arpspoofer .Start ()
1484+ }
14841485 var tproxyServer * tproxyServer
14851486 if p .tproxyAddr != "" {
14861487 tproxyServer = newTproxyServer (p )
@@ -1508,6 +1509,12 @@ func (p *proxyapp) Run() {
15081509 if p .httpServer != nil {
15091510 go func () {
15101511 <- quit
1512+ if p .arpspoofer != nil {
1513+ err := p .arpspoofer .Stop ()
1514+ if err != nil {
1515+ p .logger .Error ().Err (err ).Msg ("Failed stopping arp spoofer" )
1516+ }
1517+ }
15111518 if p .auto {
15121519 err := p .clearRedirectRules (output )
15131520 if err != nil {
@@ -1550,6 +1557,12 @@ func (p *proxyapp) Run() {
15501557 } else {
15511558 go func () {
15521559 <- quit
1560+ if p .arpspoofer != nil {
1561+ err := p .arpspoofer .Stop ()
1562+ if err != nil {
1563+ p .logger .Error ().Err (err ).Msg ("Failed stopping arp spoofer" )
1564+ }
1565+ }
15531566 if p .auto {
15541567 err := p .clearRedirectRules (output )
15551568 if err != nil {
@@ -1706,6 +1719,9 @@ func New(conf *Config) *proxyapp {
17061719 result = domainPattern .ReplaceAllStringFunc (result , func (match string ) string {
17071720 return colors .Yellow (match ).String ()
17081721 })
1722+ result = macPattern .ReplaceAllStringFunc (result , func (match string ) string {
1723+ return colors .Yellow (match ).String ()
1724+ })
17091725 return result
17101726 }
17111727
@@ -1819,11 +1835,41 @@ func New(conf *Config) *proxyapp {
18191835 if p .mark == 0 && p .tproxyMode == "tproxy" {
18201836 p .mark = 100
18211837 }
1822- p .arp = conf .ARP
1823- if p .arp && runtime .GOOS != "linux" {
1824- p .logger .Fatal ().Msg ("ARP setup is available only for linux system" )
1825- } else if p .arp && ! p .auto {
1826- p .logger .Fatal ().Msg ("ARP setup requires auto configuration" )
1838+ if conf .ARPSpoof != "" {
1839+ if runtime .GOOS != "linux" {
1840+ p .logger .Fatal ().Msg ("ARP spoof setup is available only for linux system" )
1841+ }
1842+ if ! p .auto {
1843+ p .logger .Warn ().Msg ("ARP spoof setup requires iptables configuration" )
1844+ }
1845+ asc := & arpspoof.ARPSpoofConfig {Logger : p .logger }
1846+ errMsg := `Failed parsing arp options. Example: "targets 10.0.0.1,10.0.0.5-10,192.168.1.*,192.168.10.0/24;fullduplex false;debug true"`
1847+ for opt := range strings .SplitSeq (strings .ToLower (conf .ARPSpoof ), ";" ) {
1848+ keyval := strings .SplitN (strings .Trim (opt , " " ), " " , 2 )
1849+ if len (keyval ) < 2 {
1850+ p .logger .Fatal ().Msg (errMsg )
1851+ }
1852+ key := keyval [0 ]
1853+ val := keyval [1 ]
1854+ switch key {
1855+ case "targets" :
1856+ asc .Targets = val
1857+ case "fullduplex" :
1858+ if val == "true" {
1859+ asc .FullDuplex = true
1860+ }
1861+ case "debug" :
1862+ if val == "true" {
1863+ asc .Debug = true
1864+ }
1865+ default :
1866+ p .logger .Fatal ().Msg (errMsg )
1867+ }
1868+ }
1869+ p .arpspoofer , err = arpspoof .NewARPSpoofer (asc )
1870+ if err != nil {
1871+ p .logger .Fatal ().Err (err ).Msg ("Failed creating arp spoofer" )
1872+ }
18271873 }
18281874 var addrHTTP , addrSOCKS , certFile , keyFile string
18291875 if conf .ServerConfPath != "" {
0 commit comments