-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathmain.go
More file actions
107 lines (97 loc) · 2.75 KB
/
main.go
File metadata and controls
107 lines (97 loc) · 2.75 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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main
import (
"encoding/binary"
"flag"
"fmt"
"net"
"os"
"os/exec"
"os/signal"
"syscall"
"github.com/celzero/firestack/intra"
"github.com/celzero/firestack/intra/backend"
"github.com/celzero/firestack/intra/settings"
"github.com/celzero/firestack/linux-tool/glue"
)
func p(e error) {
if e != nil {
panic(e)
}
}
func sendTUN(name string) {
sock := int(3)
defer syscall.Close(sock)
syscall.SetNonblock(sock, true)
tun, err := glue.OpenTUN(name)
p(err)
defer syscall.Close(tun)
ifInfo, err := net.InterfaceByName(name)
p(err)
var msg [4]byte
binary.NativeEndian.PutUint32(msg[:], uint32(ifInfo.MTU))
cmsg := glue.GenFDCmsg([]uint32{uint32(tun)})
err = syscall.Sendmsg(sock, msg[:], cmsg, nil, 0)
p(err)
}
func demo(targetPid int, tunName string, fakeDNS string) {
pair, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_SEQPACKET, 0)
p(err)
defer func() {
syscall.Close(pair[0])
syscall.Close(pair[1])
}()
syscall.SetNonblock(pair[0], true)
elfPath, err := os.Executable()
p(err)
c1 := exec.Command("/usr/bin/nsenter", "--target", fmt.Sprintf("%d", targetPid), "--user", "--net",
"--preserve-credentials", "--keep-caps",
elfPath, "-mode", "sendfd", "-tun", tunName)
c1.ExtraFiles = []*os.File{os.NewFile(uintptr(pair[1]), "")}
fmt.Println("starting child...")
output, err := c1.CombinedOutput()
if len(output) > 0 {
fmt.Printf("child's output:\n%s\n", string(output))
}
p(err)
var buf [4]byte
var cmsgBuf [20]byte
n, cmsgN, msgFlag, _, err := syscall.Recvmsg(pair[0], buf[:], cmsgBuf[:], 0)
p(err)
fmt.Printf("msg: %v\ncmsg: %v\nflag: %d\n", buf[:n], cmsgBuf[:cmsgN], msgFlag)
tun := int(binary.NativeEndian.Uint32(cmsgBuf[16:]))
defer syscall.Close(tun)
mtu := binary.NativeEndian.Uint32(buf[:])
settings.SetDialerOpts(settings.SplitDesync, settings.RetryNever, 0, false)
bridge := glue.MyBridge{
PIDCSV: backend.Base,
TIDCSV: backend.Preferred,
}
tunnel, err := intra.NewTunnel(tun, int(mtu), fakeDNS, nil, &bridge)
p(err)
defer tunnel.Disconnect()
err = intra.AddDoHTransport(tunnel, backend.Preferred, "https://[2620:fe::12]/dns-query", "2620:fe::12")
p(err)
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
wait1 := <-ch
fmt.Printf("received %v signal, exiting\n", wait1)
}
func main() {
var mode string
flag.StringVar(&mode, "mode", "main", "main or sendfd")
var tunName string
flag.StringVar(&tunName, "tun", "tun0", "")
var pid int
flag.IntVar(&pid, "target", -1, "target process to get namespaces from")
var fakeDNS string
flag.StringVar(&fakeDNS, "dns", "10.0.2.3:53", "DNS passed to intra.NewTunnel()")
flag.Parse()
switch mode {
case "main":
demo(pid, tunName, fakeDNS)
case "sendfd":
sendTUN(tunName)
default:
fmt.Printf("unknown mode: %s\n", mode)
}
}