Skip to content

Commit ce25f32

Browse files
committed
finish inverse role server support for webtunnel
1 parent b41e18e commit ce25f32

File tree

11 files changed

+155
-10
lines changed

11 files changed

+155
-10
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package generateRandomData
2+
3+
import "github.com/v2fly/v2ray-core/v5/common/errors"
4+
5+
type errPathObjHolder struct{}
6+
7+
func newError(values ...interface{}) *errors.Error {
8+
return errors.New(values...).WithPathObj(errPathObjHolder{})
9+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package generateRandomData
2+
3+
import (
4+
"crypto/rand"
5+
"encoding/base64"
6+
"flag"
7+
"fmt"
8+
9+
"github.com/v2fly/v2ray-core/v5/main/commands/all/engineering"
10+
"github.com/v2fly/v2ray-core/v5/main/commands/base"
11+
)
12+
13+
//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
14+
15+
var length *int
16+
17+
var cmdGenerateRandomData = &base.Command{
18+
UsageLine: "{{.Exec}} engineering generate-random-data",
19+
Short: "generate random data and output as base64",
20+
Long: `
21+
Generate random data of specified length and output as base64 encoded string.
22+
23+
Usage:
24+
{{.Exec}} engineering generate-random-data -length <bytes>
25+
26+
Options:
27+
-length <bytes>
28+
The number of random bytes to generate (required)
29+
30+
Example:
31+
{{.Exec}} engineering generate-random-data -length 32
32+
`,
33+
Flag: func() flag.FlagSet {
34+
fs := flag.NewFlagSet("", flag.ExitOnError)
35+
length = fs.Int("length", 0, "number of random bytes to generate")
36+
return *fs
37+
}(),
38+
Run: func(cmd *base.Command, args []string) {
39+
err := cmd.Flag.Parse(args)
40+
if err != nil {
41+
base.Fatalf("failed to parse flags: %v", err)
42+
}
43+
44+
if *length <= 0 {
45+
base.Fatalf("length must be a positive integer, got: %d", *length)
46+
}
47+
48+
// Generate random data
49+
randomData := make([]byte, *length)
50+
_, err = rand.Read(randomData)
51+
if err != nil {
52+
base.Fatalf("failed to generate random data: %v", err)
53+
}
54+
55+
// Encode to base64
56+
encoded := base64.StdEncoding.EncodeToString(randomData)
57+
58+
// Output the result
59+
fmt.Println(encoded)
60+
},
61+
}
62+
63+
func init() {
64+
engineering.AddCommand(cmdGenerateRandomData)
65+
}

main/distro/all/all.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ import (
113113

114114
// engineering commands
115115
_ "github.com/v2fly/v2ray-core/v5/main/commands/all/engineering"
116+
_ "github.com/v2fly/v2ray-core/v5/main/commands/all/engineering/generateRandomData"
116117

117118
// Commands that rely on jsonv4 format This disable selective compile
118119
_ "github.com/v2fly/v2ray-core/v5/main/commands/all/api/jsonv4"

transport/internet/request/roundtripper/httprt/httprt.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func (h *httpTripperClient) RoundTrip(ctx context.Context, req request.Request,
8282
if err != nil {
8383
return request.Response{}, err
8484
}
85-
return request.Response{Data: result}, err
85+
return request.Response{Data: result}, nil
8686
}
8787
_, err = io.Copy(streamingWriter, httpResp.Body)
8888
if err != nil {
@@ -170,10 +170,10 @@ func (h *httpTripperServer) Start() error {
170170
h.listener = listener
171171
go func() {
172172
httpServer := http.Server{
173-
ReadHeaderTimeout: 15 * time.Second,
174-
ReadTimeout: 15 * time.Second,
175-
WriteTimeout: 10 * time.Second,
176-
IdleTimeout: 30 * time.Second,
173+
ReadHeaderTimeout: 240 * time.Second,
174+
ReadTimeout: 240 * time.Second,
175+
WriteTimeout: 240 * time.Second,
176+
IdleTimeout: 240 * time.Second,
177177
}
178178
httpServer.Handler = h
179179
err := httpServer.Serve(h.listener)

transport/internet/request/roundtripperreverserserver/reverser.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ func (s *Reverser) OnRoundTrip(ctx context.Context, req request.Request, opts ..
4646
}
4747
return reverserImpl, nil
4848
}
49+
if len(req.ConnectionTag) != 32 {
50+
return request.Response{}, newError("invalid ConnectionTag length")
51+
}
4952
reverserImpl, err := s.reverser.OnOtherRoundTrip(ctx, req, opts...)
5053
if err != nil {
5154
return request.Response{}, newError("failed to handle client round trip").Base(err).AtError()

transport/internet/request/roundtripperreverserserver/reverserimpl.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ func (r *ReverserImpl) OnOtherRoundTrip(ctx context.Context, req request.Request
9393
messageQueue: make(chan *reverserMessage, 1),
9494
})
9595
state := stateInterface.(*clientState)
96+
defer func() {
97+
r.clientTemporaryKeyToStateMap.Delete(string(sourceKey))
98+
}()
9699

97100
serverStateInterface, ok := r.serverPublicKeyToStateMap.Load(string(destKey))
98101
if ok {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package mirrorenrollment
2+
3+
import (
4+
"context"
5+
"net"
6+
)
7+
8+
func NewCancelContextOnCloseConn(conn net.Conn, done context.CancelFunc) net.Conn {
9+
return &cancelContextOnCloseConn{
10+
Conn: conn,
11+
done: done,
12+
}
13+
}
14+
15+
type cancelContextOnCloseConn struct {
16+
net.Conn
17+
done context.CancelFunc
18+
}
19+
20+
func (c *cancelContextOnCloseConn) Close() error {
21+
c.done()
22+
return c.Conn.Close()
23+
}

transport/internet/tlsmirror/mirrorenrollment/client.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,14 @@ func (c *EnrollmentConfirmationClient) init() error {
9898
primaryConfirmationOutbound = transportEnvironment.SelfProxyTag()
9999
loopbackProtectedCtx = mirrorcommon.SetSecondaryLoopbackProtectionFlagForContext(c.ctx, c.serverIdentity)
100100
}
101-
return dialer(loopbackProtectedCtx, dest, primaryConfirmationOutbound)
101+
connContext, done := context.WithCancel(loopbackProtectedCtx)
102+
conn, err := dialer(connContext, dest, primaryConfirmationOutbound)
103+
if err != nil {
104+
done()
105+
return nil, newError("failed to dial to destination").Base(err).AtError()
106+
}
107+
contextLinkedConn := NewCancelContextOnCloseConn(conn, done)
108+
return contextLinkedConn, nil
102109
}, c.serverIdentity)
103110
if err != nil {
104111
return newError("failed to create HTTP round tripper for enrollment confirmation").Base(err).AtError()

transport/internet/tlsmirror/mirrorenrollment/httpenrollmentconfirmation/clientbuilder.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ import (
55
"net"
66
"net/http"
77
"sync"
8+
"time"
89

10+
"github.com/desertbit/timer"
911
"github.com/v2fly/v2ray-core/v5/common"
12+
"github.com/v2fly/v2ray-core/v5/common/signal/done"
1013
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror"
1114
"github.com/v2fly/v2ray-core/v5/transport/internet/tlsmirror/httponconnection"
1215
)
@@ -81,8 +84,30 @@ func (c *clientRoundtripper) roundTrip(request *http.Request) (*http.Response, e
8184
}
8285
defer c.currentConnLock.RUnlock()
8386

87+
timeoutTimer := timer.NewTimer(30 * time.Second)
88+
defer timeoutTimer.Stop()
89+
90+
waitForConnection := done.New()
91+
92+
var resp *http.Response
93+
var error_resp_ error
94+
var err error
95+
96+
go func() {
97+
resp_, err_ := c.currentConn.RoundTrip(request)
98+
resp = resp_
99+
error_resp_ = err_
100+
waitForConnection.Close()
101+
}()
102+
103+
select {
104+
case <-timeoutTimer.C:
105+
err = newError("timeout during enrollment verification round trip")
106+
case <-waitForConnection.Wait():
107+
err = error_resp_
108+
}
109+
84110
// Use the current connection to perform the round trip
85-
resp, err := c.currentConn.RoundTrip(request)
86111
if err != nil {
87112
defer func() {
88113
c.currentConnLock.RUnlock()

transport/internet/tlsmirror/mirrorenrollment/roundtripperenrollmentconfirmation/serverinverserole.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ func NewServerInverseRole(ctx context.Context, config *ServerInverseRoleConfig)
5555

5656
rttClient.OnTransportClientAssemblyReady(c)
5757

58+
go c.worker(ctx)
59+
5860
return c, nil
5961
}
6062

@@ -78,6 +80,7 @@ func (c *ServerInverseRole) worker(ctx context.Context) {
7880
newError("error polling remote for enrollment").Base(err).AtWarning().WriteToLog()
7981
}
8082
}
83+
newError("inverse role server quitted").AtWarning().WriteToLog()
8184
}
8285

8386
func (c *ServerInverseRole) Dial(ctx context.Context) (net.Conn, error) {
@@ -149,14 +152,15 @@ func (s *ServerInverseRole) pollRemoteForEnrollment(ctx context.Context) error {
149152
if err != nil {
150153
return newError("failed to marshal enrollment confirmation response").Base(err).AtError()
151154
}
152-
respAs := append(s.config.ServerIdentity, enrollmentReq.ClientIdentifier...) //nolint:gocritic
155+
respAs := append(s.config.ServerIdentity, enrollmentReq.ReplyAddressTag...) //nolint:gocritic
153156
_, err = s.rttClient.RoundTrip(ctx, request.Request{
154157
Data: respData,
155158
ConnectionTag: respAs,
156159
})
157160
if err != nil {
158161
return newError("failed to send enrollment confirmation response back to remote").Base(err)
159162
}
163+
newError("successfully processed enrollment confirmation request").AtDebug().WriteToLog()
160164
return nil
161165
}
162166

0 commit comments

Comments
 (0)