@@ -7,10 +7,13 @@ import (
77 "context"
88 "errors"
99 "fmt"
10+ "maps"
1011 "net"
1112 "net/netip"
1213 "os"
1314 "os/exec"
15+ "slices"
16+ "strings"
1417 "sync"
1518 "syscall"
1619 "time"
@@ -254,12 +257,34 @@ func getBaseDialer(timeout time.Duration, mark uint) *net.Dialer {
254257 return dialer
255258}
256259
257- func (ts * tproxyServer ) applyRedirectRules () string {
260+ func (ts * tproxyServer ) createSysctlOptCmd (opt , value , setex string , opts map [string ]string ) * exec.Cmd {
261+ cmdCat := exec .Command ("bash" , "-c" , fmt .Sprintf (`
262+ cat /proc/sys/%s
263+ ` , strings .ReplaceAll (opt , "." , "/" )))
264+ output , err := cmdCat .CombinedOutput ()
265+ if err != nil {
266+ ts .p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
267+ }
268+ opts [opt ] = string (output )
269+ cmd := exec .Command ("bash" , "-c" , fmt .Sprintf (`
270+ %s
271+ sysctl -w %s=%s
272+ ` , setex , opt , value ))
273+ cmd .Stdout = os .Stdout
274+ cmd .Stderr = os .Stderr
275+ if ! ts .p .debug {
276+ cmd .Stdout = nil
277+ }
278+ return cmd
279+ }
280+
281+ func (ts * tproxyServer ) applyRedirectRules () map [string ]string {
258282 _ , tproxyPort , _ := net .SplitHostPort (ts .p .tproxyAddr )
259283 var setex string
260284 if ts .p .debug {
261285 setex = "set -ex"
262286 }
287+ ipv4Settings := make (map [string ]string , 5 )
263288 switch ts .p .tproxyMode {
264289 case "redirect" :
265290 cmdClear := exec .Command ("bash" , "-c" , fmt .Sprintf (`
@@ -427,23 +452,21 @@ func (ts *tproxyServer) applyRedirectRules() string {
427452 default :
428453 ts .p .logger .Fatal ().Msgf ("Unreachable, unknown mode: %s" , ts .p .tproxyMode )
429454 }
430- cmdCat := exec .Command ("bash" , "-c" , `
431- cat /proc/sys/net/ipv4/ip_forward
432- ` )
433- output , err := cmdCat .CombinedOutput ()
434- if err != nil {
435- ts .p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
436- }
437- cmdForward := exec .Command ("bash" , "-c" , fmt .Sprintf (`
455+ _ = ts .createSysctlOptCmd ("net.ipv4.ip_forward" , "1" , setex , ipv4Settings ).Run ()
456+ cmdCheckBBR := exec .Command ("bash" , "-c" , fmt .Sprintf (`
438457 %s
439- sysctl -w net.ipv4.ip_forward=1
458+ lsmod | grep -q '^tcp_bbr' || modprobe tcp_bbr
440459 ` , setex ))
441- cmdForward .Stdout = os .Stdout
442- cmdForward .Stderr = os .Stderr
460+ cmdCheckBBR .Stdout = os .Stdout
461+ cmdCheckBBR .Stderr = os .Stderr
443462 if ! ts .p .debug {
444- cmdForward .Stdout = nil
463+ cmdCheckBBR .Stdout = nil
445464 }
446- _ = cmdForward .Run ()
465+ _ = cmdCheckBBR .Run ()
466+ _ = ts .createSysctlOptCmd ("net.ipv4.tcp_congestion_control" , "bbr" , setex , ipv4Settings ).Run ()
467+ _ = ts .createSysctlOptCmd ("net.core.default_qdisc" , "fq" , setex , ipv4Settings ).Run ()
468+ _ = ts .createSysctlOptCmd ("net.ipv4.tcp_tw_reuse" , "1" , setex , ipv4Settings ).Run ()
469+ _ = ts .createSysctlOptCmd ("net.ipv4.tcp_fin_timeout" , "15" , setex , ipv4Settings ).Run ()
447470 cmdClearForward := exec .Command ("bash" , "-c" , fmt .Sprintf (`
448471 %s
449472 iptables -t filter -F GOHPTS 2>/dev/null || true
@@ -456,6 +479,7 @@ func (ts *tproxyServer) applyRedirectRules() string {
456479 ts .p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
457480 }
458481 var iface * net.Interface
482+ var err error
459483 if ts .p .iface != nil {
460484 iface = ts .p .iface
461485 } else {
@@ -477,10 +501,10 @@ func (ts *tproxyServer) applyRedirectRules() string {
477501 if err := cmdForwardFilter .Run (); err != nil {
478502 ts .p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
479503 }
480- return string ( output )
504+ return ipv4Settings
481505}
482506
483- func (ts * tproxyServer ) clearRedirectRules (output string ) error {
507+ func (ts * tproxyServer ) clearRedirectRules (opts map [ string ] string ) error {
484508 var setex string
485509 if ts .p .debug {
486510 setex = "set -ex"
@@ -496,6 +520,20 @@ func (ts *tproxyServer) clearRedirectRules(output string) error {
496520 if err := cmdClear .Run (); err != nil {
497521 ts .p .logger .Fatal ().Err (err ).Msg ("Failed while configuring iptables. Are you root?" )
498522 }
523+ cmds := make ([]string , 0 , len (opts ))
524+ for _ , cmd := range slices .Sorted (maps .Keys (opts )) {
525+ cmds = append (cmds , fmt .Sprintf ("sysctl -w %s=%s" , cmd , opts [cmd ]))
526+ }
527+ cmdRestoreOpts := exec .Command ("bash" , "-c" , fmt .Sprintf (`
528+ %s
529+ %s
530+ ` , setex , strings .Join (cmds , "\n " )))
531+ cmdRestoreOpts .Stdout = os .Stdout
532+ cmdRestoreOpts .Stderr = os .Stderr
533+ if ! ts .p .debug {
534+ cmdRestoreOpts .Stdout = nil
535+ }
536+ _ = cmdRestoreOpts .Run ()
499537 var cmd * exec.Cmd
500538 switch ts .p .tproxyMode {
501539 case "redirect" :
@@ -505,8 +543,7 @@ func (ts *tproxyServer) clearRedirectRules(output string) error {
505543 iptables -t nat -D OUTPUT -p tcp -j GOHPTS 2>/dev/null || true
506544 iptables -t nat -F GOHPTS 2>/dev/null || true
507545 iptables -t nat -X GOHPTS 2>/dev/null || true
508- sysctl -w net.ipv4.ip_forward=%s
509- ` , setex , output ))
546+ ` , setex ))
510547 cmd .Stdout = os .Stdout
511548 cmd .Stderr = os .Stderr
512549 case "tproxy" :
@@ -521,8 +558,7 @@ func (ts *tproxyServer) clearRedirectRules(output string) error {
521558
522559 ip rule del fwmark 1 lookup 100 2>/dev/null || true
523560 ip route flush table 100 2>/dev/null || true
524- sysctl -w net.ipv4.ip_forward=%s
525- ` , setex , output ))
561+ ` , setex ))
526562 cmd .Stdout = os .Stdout
527563 cmd .Stderr = os .Stderr
528564 if ! ts .p .debug {
0 commit comments