-
Notifications
You must be signed in to change notification settings - Fork 188
Expand file tree
/
Copy pathredirect_iptables.go
More file actions
81 lines (72 loc) · 1.98 KB
/
redirect_iptables.go
File metadata and controls
81 lines (72 loc) · 1.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//go:build linux
package tun
import (
"os/exec"
"strings"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
)
func (r *autoRedirect) setupIPTables() error {
if r.enableIPv4 {
err := r.setupIPTablesForFamily(r.iptablesPath)
if err != nil {
return E.Cause(err, "setup iptables")
}
}
if r.enableIPv6 {
err := r.setupIPTablesForFamily(r.ip6tablesPath)
if err != nil {
return E.Cause(err, "setup ip6tables")
}
}
return nil
}
func (r *autoRedirect) setupIPTablesForFamily(iptablesPath string) error {
tableNameOutput := r.tableName + "-output"
redirectPort := r.redirectPort()
// OUTPUT
err := r.runShell(iptablesPath, "-t nat -N", tableNameOutput)
if err != nil {
return err
}
err = r.runShell(iptablesPath, "-t nat -A", tableNameOutput,
"-p tcp -o", r.tunOptions.Name,
"-j REDIRECT --to-ports", redirectPort)
if err != nil {
return err
}
err = r.runShell(iptablesPath, "-t nat -I OUTPUT -j", tableNameOutput)
if err != nil {
return err
}
return nil
}
func (r *autoRedirect) cleanupIPTables() {
if r.enableIPv4 {
r.cleanupIPTablesForFamily(r.iptablesPath)
}
if r.enableIPv6 {
r.cleanupIPTablesForFamily(r.ip6tablesPath)
}
}
func (r *autoRedirect) cleanupIPTablesForFamily(iptablesPath string) {
tableNameOutput := r.tableName + "-output"
_ = r.runShell(iptablesPath, "-t nat -D OUTPUT -j", tableNameOutput)
_ = r.runShell(iptablesPath, "-t nat -F", tableNameOutput)
_ = r.runShell(iptablesPath, "-t nat -X", tableNameOutput)
}
func (r *autoRedirect) runShell(commands ...any) error {
commandStr := strings.Join(F.MapToString(commands), " ")
var command *exec.Cmd
if r.androidSu {
command = exec.Command(r.suPath, "-c", commandStr)
} else {
commandArray := strings.Split(commandStr, " ")
command = exec.Command(commandArray[0], commandArray[1:]...)
}
combinedOutput, err := command.CombinedOutput()
if err != nil {
return E.Extend(err, F.ToString(commandStr, ": ", string(combinedOutput)))
}
return nil
}