@@ -18,6 +18,7 @@ import (
1818 "net"
1919 "net/http"
2020 "os"
21+ "os/exec"
2122 "os/signal"
2223 "regexp"
2324 "runtime"
@@ -86,6 +87,7 @@ type Config struct {
8687 TProxy string
8788 TProxyOnly string
8889 TProxyMode string
90+ Auto bool
8991 LogFilePath string
9092 Debug bool
9193 Json bool
@@ -107,6 +109,7 @@ type proxyapp struct {
107109 httpServerAddr string
108110 tproxyAddr string
109111 tproxyMode string
112+ auto bool
110113 user string
111114 pass string
112115 proxychain chain
@@ -1143,6 +1146,99 @@ func (p *proxyapp) handler() http.HandlerFunc {
11431146 }
11441147}
11451148
1149+ func (p * proxyapp ) applyRedirectRules () string {
1150+ cmd0 := exec .Command ("bash" , "-c" , `
1151+ set -ex
1152+ iptables -t nat -D PREROUTING -p tcp -j GOHPTS 2>/dev/null || true
1153+ iptables -t nat -D OUTPUT -p tcp -j GOHPTS 2>/dev/null || true
1154+ iptables -t nat -F GOHPTS 2>/dev/null || true
1155+ iptables -t nat -X GOHPTS 2>/dev/null || true
1156+ ` )
1157+ cmd0 .Stdout = os .Stdout
1158+ cmd0 .Stderr = os .Stderr
1159+ if err := cmd0 .Run (); err != nil {
1160+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1161+ }
1162+ _ , tproxyPort , _ := net .SplitHostPort (p .tproxyAddr )
1163+ cmd1 := exec .Command ("bash" , "-c" , fmt .Sprintf (`
1164+ set -ex
1165+ iptables -t nat -N GOHPTS 2>/dev/null
1166+ iptables -t nat -F GOHPTS
1167+
1168+ iptables -t nat -A GOHPTS -d 127.0.0.0/8 -j RETURN
1169+ iptables -t nat -A GOHPTS -p tcp --dport %s -j RETURN
1170+ iptables -t nat -A GOHPTS -p tcp --dport 22 -j RETURN
1171+ ` , tproxyPort ))
1172+ cmd1 .Stdout = os .Stdout
1173+ cmd1 .Stderr = os .Stderr
1174+ if err := cmd1 .Run (); err != nil {
1175+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1176+ }
1177+ if p .httpServerAddr != "" {
1178+ _ , httpPort , _ := net .SplitHostPort (p .httpServerAddr )
1179+ cmd2 := exec .Command ("bash" , "-c" , fmt .Sprintf (`
1180+ set -ex
1181+ iptables -t nat -A GOHPTS -p tcp --dport %s -j RETURN
1182+ ` , httpPort ))
1183+ cmd2 .Stdout = os .Stdout
1184+ cmd2 .Stderr = os .Stderr
1185+ if err := cmd2 .Run (); err != nil {
1186+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1187+ }
1188+ }
1189+ cmd3 := exec .Command ("bash" , "-c" , fmt .Sprintf (`
1190+ set -ex
1191+ if command -v docker >/dev/null 2>&1
1192+ then
1193+ for subnet in $(docker network inspect $(docker network ls -q) --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'); do
1194+ iptables -t nat -A GOHPTS -d "$subnet" -j RETURN
1195+ done
1196+ fi
1197+
1198+ iptables -t nat -A GOHPTS -p tcp -j REDIRECT --to-ports %s
1199+
1200+ iptables -t nat -C PREROUTING -p tcp -j GOHPTS 2>/dev/null || \
1201+ iptables -t nat -A PREROUTING -p tcp -j GOHPTS
1202+
1203+ iptables -t nat -C OUTPUT -p tcp -j GOHPTS 2>/dev/null || \
1204+ iptables -t nat -A OUTPUT -p tcp -j GOHPTS
1205+ ` , tproxyPort ))
1206+ cmd3 .Stdout = os .Stdout
1207+ cmd3 .Stderr = os .Stderr
1208+ if err := cmd3 .Run (); err != nil {
1209+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1210+ }
1211+ cmd4 := exec .Command ("bash" , "-c" , `
1212+ cat /proc/sys/net/ipv4/ip_forward
1213+ ` )
1214+ output , err := cmd4 .CombinedOutput ()
1215+ if err != nil {
1216+ p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
1217+ }
1218+ cmd5 := exec .Command ("bash" , "-c" , `
1219+ set -ex
1220+ sysctl -w net.ipv4.ip_forward=1
1221+ ` )
1222+ cmd5 .Stdout = os .Stdout
1223+ cmd5 .Stderr = os .Stderr
1224+ _ = cmd5 .Run ()
1225+ return string (output )
1226+ }
1227+
1228+ func (p * proxyapp ) clearRedirectRules (output string ) error {
1229+ cmd := exec .Command ("bash" , "-c" , fmt .Sprintf (`
1230+ set -ex
1231+ iptables -t nat -D PREROUTING -p tcp -j GOHPTS 2>/dev/null || true
1232+ iptables -t nat -D OUTPUT -p tcp -j GOHPTS 2>/dev/null || true
1233+ iptables -t nat -F GOHPTS 2>/dev/null || true
1234+ iptables -t nat -X GOHPTS 2>/dev/null || true
1235+ sysctl -w net.ipv4.ip_forward=%s
1236+ ` , output ))
1237+ cmd .Stdout = os .Stdout
1238+ cmd .Stderr = os .Stderr
1239+ return cmd .Run ()
1240+ }
1241+
11461242func (p * proxyapp ) Run () {
11471243 done := make (chan bool )
11481244 quit := make (chan os.Signal , 1 )
@@ -1151,6 +1247,10 @@ func (p *proxyapp) Run() {
11511247 if p .tproxyAddr != "" {
11521248 tproxyServer = newTproxyServer (p )
11531249 }
1250+ var output string
1251+ if p .auto {
1252+ output = p .applyRedirectRules ()
1253+ }
11541254 if p .proxylist != nil {
11551255 chainType := p .proxychain .Type
11561256 var ctl string
@@ -1170,6 +1270,12 @@ func (p *proxyapp) Run() {
11701270 if p .httpServer != nil {
11711271 go func () {
11721272 <- quit
1273+ if p .auto {
1274+ err := p .clearRedirectRules (output )
1275+ if err != nil {
1276+ p .logger .Error ().Err (err ).Msg ("Failed clearing iptables rules" )
1277+ }
1278+ }
11731279 if tproxyServer != nil {
11741280 p .logger .Info ().Msg ("[tproxy] Server is shutting down..." )
11751281 tproxyServer .Shutdown ()
@@ -1205,6 +1311,12 @@ func (p *proxyapp) Run() {
12051311 } else {
12061312 go func () {
12071313 <- quit
1314+ if p .auto {
1315+ err := p .clearRedirectRules (output )
1316+ if err != nil {
1317+ p .logger .Error ().Err (err ).Msg ("Failed clearing iptables rules" )
1318+ }
1319+ }
12081320 p .logger .Info ().Msg ("[tproxy] Server is shutting down..." )
12091321 tproxyServer .Shutdown ()
12101322 close (done )
@@ -1259,20 +1371,26 @@ type serverConfig struct {
12591371 Server server `yaml:"server"`
12601372}
12611373
1262- func getFullAddress (v string ) string {
1374+ func getFullAddress (v string ) ( string , error ) {
12631375 if v == "" {
1264- return ""
1265- }
1266- var addr string
1267- i , err := strconv .Atoi (v )
1268- if err == nil {
1269- addr = fmt .Sprintf ("127.0.0.1:%d" , i )
1270- } else if strings .HasPrefix (v , ":" ) {
1271- addr = fmt .Sprintf ("127.0.0.1%s" , v )
1272- } else {
1273- addr = v
1376+ return "" , nil
1377+ }
1378+ if i , err := strconv .Atoi (v ); err == nil {
1379+ return fmt .Sprintf ("127.0.0.1:%d" , i ), nil
1380+ }
1381+ host , port , err := net .SplitHostPort (v )
1382+ if err != nil {
1383+ return "" , err
1384+ }
1385+ if host != "" && port == "" {
1386+ return "" , fmt .Errorf ("port is missing" )
1387+ }
1388+ if host != "" && port != "" {
1389+ return v , nil
1390+ } else if port != "" {
1391+ return fmt .Sprintf ("127.0.0.1:%s" , port ), nil
12741392 }
1275- return addr
1393+ return "" , fmt . Errorf ( "failed parsing address" )
12761394}
12771395
12781396func expandPath (p string ) string {
@@ -1290,6 +1408,7 @@ func New(conf *Config) *proxyapp {
12901408 var p proxyapp
12911409 var logfile * os.File = os .Stdout
12921410 var snifflog * os.File
1411+ var err error
12931412 p .sniff = conf .Sniff
12941413 p .body = conf .Body
12951414 p .json = conf .Json
@@ -1418,9 +1537,19 @@ func New(conf *Config) *proxyapp {
14181537 p .tproxyMode = conf .TProxyMode
14191538 tproxyonly := conf .TProxyOnly != ""
14201539 if tproxyonly {
1421- p .tproxyAddr = getFullAddress (conf .TProxyOnly )
1540+ p .tproxyAddr , err = getFullAddress (conf .TProxyOnly )
1541+ if err != nil {
1542+ p .logger .Fatal ().Err (err ).Msg ("" )
1543+ }
14221544 } else {
1423- p .tproxyAddr = getFullAddress (conf .TProxy )
1545+ p .tproxyAddr , err = getFullAddress (conf .TProxy )
1546+ if err != nil {
1547+ p .logger .Fatal ().Err (err ).Msg ("" )
1548+ }
1549+ }
1550+ p .auto = conf .Auto
1551+ if p .auto && p .tproxyMode != "" && p .tproxyMode != "redirect" {
1552+ p .logger .Fatal ().Msg ("Auto setup is available only for redirect mode" )
14241553 }
14251554 var addrHTTP , addrSOCKS , certFile , keyFile string
14261555 if conf .ServerConfPath != "" {
@@ -1437,7 +1566,10 @@ func New(conf *Config) *proxyapp {
14371566 if sconf .Server .Address == "" {
14381567 p .logger .Fatal ().Err (err ).Msg ("[server config] Server address is empty" )
14391568 }
1440- addrHTTP = getFullAddress (sconf .Server .Address )
1569+ addrHTTP , err = getFullAddress (sconf .Server .Address )
1570+ if err != nil {
1571+ p .logger .Fatal ().Err (err ).Msg ("" )
1572+ }
14411573 p .httpServerAddr = addrHTTP
14421574 certFile = expandPath (sconf .Server .CertFile )
14431575 keyFile = expandPath (sconf .Server .KeyFile )
@@ -1452,7 +1584,10 @@ func New(conf *Config) *proxyapp {
14521584 }
14531585 seen := make (map [string ]struct {})
14541586 for idx , pr := range p .proxylist {
1455- addr := getFullAddress (pr .Address )
1587+ addr , err := getFullAddress (pr .Address )
1588+ if err != nil {
1589+ p .logger .Fatal ().Err (err ).Msg ("" )
1590+ }
14561591 if _ , ok := seen [addr ]; ! ok {
14571592 seen [addr ] = struct {}{}
14581593 p .proxylist [idx ].Address = addr
@@ -1468,14 +1603,20 @@ func New(conf *Config) *proxyapp {
14681603 p .rrIndexReset = rrIndexMax
14691604 } else {
14701605 if ! tproxyonly {
1471- addrHTTP = getFullAddress (conf .AddrHTTP )
1606+ addrHTTP , err = getFullAddress (conf .AddrHTTP )
1607+ if err != nil {
1608+ p .logger .Fatal ().Err (err ).Msg ("" )
1609+ }
14721610 p .httpServerAddr = addrHTTP
14731611 certFile = expandPath (conf .CertFile )
14741612 keyFile = expandPath (conf .KeyFile )
14751613 p .user = conf .ServerUser
14761614 p .pass = conf .ServerPass
14771615 }
1478- addrSOCKS = getFullAddress (conf .AddrSOCKS )
1616+ addrSOCKS , err = getFullAddress (conf .AddrSOCKS )
1617+ if err != nil {
1618+ p .logger .Fatal ().Err (err ).Msg ("" )
1619+ }
14791620 auth := proxy.Auth {
14801621 User : conf .User ,
14811622 Password : conf .Pass ,
0 commit comments