Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ulixee
GitHub Repository: ulixee/secret-agent
Path: blob/main/mitm-socket/go/connect.go
1029 views
1
package main
2
3
import (
4
"bufio"
5
"encoding/json"
6
"fmt"
7
"log"
8
"net"
9
"os"
10
"time"
11
12
utls "github.com/ulixee/utls"
13
)
14
15
const CertsMode = "certs"
16
17
func main() {
18
var sessionArgs = SessionArgs{}
19
var certConfig *CertConfig
20
json.Unmarshal([]byte(os.Args[1]), &sessionArgs)
21
22
signals := RegisterSignals()
23
24
if sessionArgs.Debug {
25
fmt.Printf("SessionArgs %#v\n", sessionArgs)
26
}
27
28
conn, err := ConnectIpc(sessionArgs.IpcSocketPath)
29
if err != nil {
30
log.Fatalf("Listening to Ipc DomainSocket Error: %+v\n", err)
31
}
32
defer conn.Close()
33
34
if sessionArgs.Mode == CertsMode {
35
certConfig, err = NewCertConfig(nil, nil)
36
if err != nil {
37
log.Fatalf("Initializing Cert Config Error: %+v\n", err)
38
}
39
40
SendToIpc(0, "init", map[string]interface{}{
41
"privateKey": certConfig.privateKeyPEM,
42
})
43
}
44
45
var msg []byte
46
reader := bufio.NewReader(conn)
47
48
for {
49
if signals.IsClosed {
50
return
51
}
52
conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) // Set the deadline
53
54
msg, err = reader.ReadBytes('\n')
55
if err != nil {
56
time.Sleep(50 * time.Millisecond)
57
continue
58
}
59
var connectArgs = ConnectArgs{}
60
json.Unmarshal(msg, &connectArgs)
61
62
if sessionArgs.Mode == CertsMode {
63
go generateCert(certConfig, connectArgs.Id, connectArgs.Host)
64
} else {
65
go handleSocket(connectArgs, sessionArgs, signals)
66
}
67
}
68
}
69
70
func generateCert(config *CertConfig, id int, hostname string) {
71
cert, expireDate, err := config.CreateCert(hostname)
72
73
if err != nil {
74
SendErrorToIpc(id, "ipcConnect", err)
75
return
76
}
77
78
SendToIpc(id, "certs", map[string]interface{}{
79
"cert": string(cert),
80
"expireDate": expireDate,
81
})
82
}
83
84
func handleSocket(connectArgs ConnectArgs, sessionArgs SessionArgs, signals *Signals) {
85
var uTlsConn *utls.UConn
86
var protocol string
87
88
id := connectArgs.Id
89
if sessionArgs.Debug {
90
fmt.Printf("[id=%d] Serving at socket path %+s. ConnectArgs %#v\n", id, connectArgs.SocketPath, connectArgs)
91
}
92
93
domainConn, connErr := DialOnDomain(connectArgs.SocketPath)
94
defer domainConn.Close()
95
96
if connErr != nil {
97
SendErrorToIpc(id, "ipcConnect", connErr)
98
return
99
}
100
101
domainSocketPiper := &DomainSocketPiper{
102
client: domainConn,
103
id: connectArgs.Id,
104
debug: sessionArgs.Debug,
105
signals: signals,
106
}
107
defer domainSocketPiper.Close()
108
109
addr := fmt.Sprintf("%s:%s", connectArgs.Host, connectArgs.Port)
110
dialConn, connectErr := Dial(addr, connectArgs, sessionArgs)
111
112
if connectErr != nil {
113
SendErrorToIpc(id, "dial", connectErr)
114
return
115
}
116
defer dialConn.Close()
117
118
if connectArgs.IsSsl {
119
var err error
120
uTlsConn, err = EmulateTls(dialConn, addr, sessionArgs, connectArgs)
121
if err != nil {
122
SendErrorToIpc(id, "emulateTls", err)
123
return
124
}
125
protocol = uTlsConn.ConnectionState().NegotiatedProtocol
126
tcpConn, ok := dialConn.(*net.TCPConn)
127
if protocol == "h2" && ok {
128
tcpConn.SetNoDelay(true)
129
}
130
}
131
132
SendToIpc(id, "connected", map[string]interface{}{
133
"alpn": protocol,
134
"remoteAddress": dialConn.RemoteAddr().String(),
135
"localAddress": dialConn.LocalAddr().String(),
136
})
137
138
if uTlsConn != nil {
139
domainSocketPiper.Pipe(uTlsConn)
140
} else {
141
domainSocketPiper.Pipe(dialConn)
142
}
143
}
144
145
type ConnectArgs struct {
146
Id int
147
SocketPath string
148
Host string
149
Port string
150
IsSsl bool
151
Servername string
152
ProxyUrl string
153
KeepAlive bool
154
IsWebsocket bool
155
KeylogPath string
156
}
157
158
type SessionArgs struct {
159
IpcSocketPath string
160
RejectUnauthorized bool
161
ClientHelloId string
162
TcpTtl int
163
TcpWindowSize int
164
Debug bool
165
Mode string
166
}
167
168