Skip to content

Commit

Permalink
Feat: Edge IP for CDN connection
Browse files Browse the repository at this point in the history
  • Loading branch information
Musixal committed Oct 20, 2024
1 parent 21138f8 commit 5ebd7ac
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 62 deletions.
70 changes: 38 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ To start using the solution, you'll need to configure both server and client com
```toml
[client] # Behind NAT, firewall-blocked
remote_addr = "0.0.0.0:3080" # Server address and port (mandatory).
edge_ip = "188.114.96.0" # Edge IP used for CDN connection, specifically for WebSocket-based transports.(Optional, default none)
transport = "tcp" # Protocol to use ("tcp", "tcpmux", "ws", "wss", "wsmux", "wssmux". mandatory).
token = "your_token" # Authentication token for secure communication (optional).
connection_pool = 8 # Number of pre-established connections.(optional, default: 8).
Expand Down Expand Up @@ -202,38 +203,6 @@ To start using the solution, you'll need to configure both server and client com
`nodelay`: Refers to a TCP socket option (TCP_NODELAY) that improve the latency but decrease the bandwidth
#### UDP Configuration
* **Server**:
```toml
[server]
bind_addr = "0.0.0.0:3080"
transport = "udp"
token = "your_token"
heartbeat = 20
channel_size = 2048
sniffer = false
web_port = 2060
sniffer_log = "/root/backhaul.json"
log_level = "info"
ports = []
```
* **Client**:
```toml
[client]
remote_addr = "0.0.0.0:3080"
transport = "udp"
token = "your_token"
connection_pool = 8
aggressive_pool = false
retry_interval = 3
sniffer = false
web_port = 2060
sniffer_log = "/root/backhaul.json"
log_level = "info"
```
#### TCP Multiplexing Configuration
* **Server**:
Expand Down Expand Up @@ -287,6 +256,39 @@ To start using the solution, you'll need to configure both server and client com
* Refer to TCP configuration for more information.
#### UDP Configuration
* **Server**:
```toml
[server]
bind_addr = "0.0.0.0:3080"
transport = "udp"
token = "your_token"
heartbeat = 20
channel_size = 2048
sniffer = false
web_port = 2060
sniffer_log = "/root/backhaul.json"
log_level = "info"
ports = []
```
* **Client**:
```toml
[client]
remote_addr = "0.0.0.0:3080"
transport = "udp"
token = "your_token"
connection_pool = 8
aggressive_pool = false
retry_interval = 3
sniffer = false
web_port = 2060
sniffer_log = "/root/backhaul.json"
log_level = "info"
```
#### WebSocket Configuration
* **Server**:
Expand All @@ -311,6 +313,7 @@ To start using the solution, you'll need to configure both server and client com
```toml
[client]
remote_addr = "0.0.0.0:8080"
edge_ip = ""
transport = "ws"
token = "your_token"
connection_pool = 8
Expand Down Expand Up @@ -354,6 +357,7 @@ To start using the solution, you'll need to configure both server and client com
```toml
[client]
remote_addr = "0.0.0.0:8443"
edge_ip = ""
transport = "wss"
token = "your_token"
connection_pool = 8
Expand Down Expand Up @@ -401,6 +405,7 @@ To start using the solution, you'll need to configure both server and client com
```toml
[client]
remote_addr = "0.0.0.0:3080"
edge_ip = ""
transport = "wsmux"
token = "your_token"
connection_pool = 8
Expand Down Expand Up @@ -449,6 +454,7 @@ To start using the solution, you'll need to configure both server and client com
```toml
[client]
remote_addr = "0.0.0.0:443"
edge_ip = ""
transport = "wssmux"
token = "your_token"
keepalive_period = 75
Expand Down
44 changes: 23 additions & 21 deletions internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,26 @@ func (c *Client) Start() {
Sniffer: c.config.Sniffer,
WebPort: c.config.WebPort,
SnifferLog: c.config.SnifferLog,
AggressivePool: c.config.AggressivePool,
AggressivePool: c.config.AggressivePool,
}
tcpMuxClient := transport.NewMuxClient(c.ctx, tcpMuxConfig, c.logger)
go tcpMuxClient.Start()

} else if c.config.Transport == config.WS || c.config.Transport == config.WSS {
WsConfig := &transport.WsConfig{
RemoteAddr: c.config.RemoteAddr,
Nodelay: c.config.Nodelay,
KeepAlive: time.Duration(c.config.Keepalive) * time.Second,
RetryInterval: time.Duration(c.config.RetryInterval) * time.Second,
DialTimeOut: time.Duration(c.config.DialTimeout) * time.Second,
ConnPoolSize: c.config.ConnectionPool,
Token: c.config.Token,
Sniffer: c.config.Sniffer,
WebPort: c.config.WebPort,
SnifferLog: c.config.SnifferLog,
Mode: c.config.Transport,
RemoteAddr: c.config.RemoteAddr,
Nodelay: c.config.Nodelay,
KeepAlive: time.Duration(c.config.Keepalive) * time.Second,
RetryInterval: time.Duration(c.config.RetryInterval) * time.Second,
DialTimeOut: time.Duration(c.config.DialTimeout) * time.Second,
ConnPoolSize: c.config.ConnectionPool,
Token: c.config.Token,
Sniffer: c.config.Sniffer,
WebPort: c.config.WebPort,
SnifferLog: c.config.SnifferLog,
Mode: c.config.Transport,
AggressivePool: c.config.AggressivePool,
EdgeIP: c.config.EdgeIP,
}
WsClient := transport.NewWSClient(c.ctx, WsConfig, c.logger)
go WsClient.Start()
Expand All @@ -119,7 +120,8 @@ func (c *Client) Start() {
WebPort: c.config.WebPort,
SnifferLog: c.config.SnifferLog,
Mode: c.config.Transport,
AggressivePool: c.config.AggressivePool,
AggressivePool: c.config.AggressivePool,
EdgeIP: c.config.EdgeIP,
}
wsMuxClient := transport.NewWSMuxClient(c.ctx, wsMuxConfig, c.logger)
go wsMuxClient.Start()
Expand All @@ -143,14 +145,14 @@ func (c *Client) Start() {

} else if c.config.Transport == config.UDP {
udpConfig := &transport.UdpConfig{
RemoteAddr: c.config.RemoteAddr,
RetryInterval: time.Duration(c.config.RetryInterval) * time.Second,
DialTimeOut: time.Duration(c.config.DialTimeout) * time.Second,
ConnPoolSize: c.config.ConnectionPool,
Token: c.config.Token,
Sniffer: c.config.Sniffer,
WebPort: c.config.WebPort,
SnifferLog: c.config.SnifferLog,
RemoteAddr: c.config.RemoteAddr,
RetryInterval: time.Duration(c.config.RetryInterval) * time.Second,
DialTimeOut: time.Duration(c.config.DialTimeout) * time.Second,
ConnPoolSize: c.config.ConnectionPool,
Token: c.config.Token,
Sniffer: c.config.Sniffer,
WebPort: c.config.WebPort,
SnifferLog: c.config.SnifferLog,
AggressivePool: c.config.AggressivePool,
}
udpClient := transport.NewUDPClient(c.ctx, udpConfig, c.logger)
Expand Down
22 changes: 17 additions & 5 deletions internal/client/transport/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func ReusePortControl(network, address string, s syscall.RawConn) error {
return controlErr
}

func WebSocketDialer(ctx context.Context, addr string, path string, timeout time.Duration, keepalive time.Duration, nodelay bool, token string, mode config.TransportType, retry int) (*websocket.Conn, error) {
func WebSocketDialer(ctx context.Context, addr string, edgeIP string, path string, timeout time.Duration, keepalive time.Duration, nodelay bool, token string, mode config.TransportType, retry int) (*websocket.Conn, error) {
var tunnelWSConn *websocket.Conn
var err error

Expand All @@ -144,7 +144,7 @@ func WebSocketDialer(ctx context.Context, addr string, path string, timeout time

for i := 0; i < retries; i++ {
// Attempt to dial the WebSocket
tunnelWSConn, err = attemptDialWebSocket(ctx, addr, path, timeout, keepalive, nodelay, token, mode)
tunnelWSConn, err = attemptDialWebSocket(ctx, addr, edgeIP, path, timeout, keepalive, nodelay, token, mode)
if err == nil {
// If successful, return the connection
return tunnelWSConn, nil
Expand All @@ -163,22 +163,34 @@ func WebSocketDialer(ctx context.Context, addr string, path string, timeout time
return nil, err
}

func attemptDialWebSocket(ctx context.Context, addr string, path string, timeout time.Duration, keepalive time.Duration, nodelay bool, token string, mode config.TransportType) (*websocket.Conn, error) {
func attemptDialWebSocket(ctx context.Context, addr string, edgeIP string, path string, timeout time.Duration, keepalive time.Duration, nodelay bool, token string, mode config.TransportType) (*websocket.Conn, error) {
// Setup headers with authorization
headers := http.Header{}
headers.Add("Authorization", fmt.Sprintf("Bearer %v", token))

var wsURL string
dialer := websocket.Dialer{}

// Handle edgeIP assignment
if edgeIP != "" {
_, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, fmt.Errorf("invalid address format, failed to parse: %w", err)
}

edgeIP = fmt.Sprintf("%s:%s", edgeIP, port)
} else {
edgeIP = addr
}

if mode == config.WS || mode == config.WSMUX {
wsURL = fmt.Sprintf("ws://%s%s", addr, path)

dialer = websocket.Dialer{
EnableCompression: true,
HandshakeTimeout: 45 * time.Second, // default handshake timeout
NetDial: func(_, addr string) (net.Conn, error) {
conn, err := TcpDialer(ctx, addr, timeout, keepalive, nodelay, 1)
conn, err := TcpDialer(ctx, edgeIP, timeout, keepalive, nodelay, 1)
if err != nil {
return nil, err
}
Expand All @@ -198,7 +210,7 @@ func attemptDialWebSocket(ctx context.Context, addr string, path string, timeout
TLSClientConfig: tlsConfig, // Pass the insecure TLS config here
HandshakeTimeout: 45 * time.Second, // default handshake timeout
NetDial: func(_, addr string) (net.Conn, error) {
conn, err := TcpDialer(ctx, addr, timeout, keepalive, nodelay, 1)
conn, err := TcpDialer(ctx, edgeIP, timeout, keepalive, nodelay, 1)
if err != nil {
return nil, err
}
Expand Down
5 changes: 3 additions & 2 deletions internal/client/transport/ws.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type WsConfig struct {
WebPort int
Mode config.TransportType
AggressivePool bool
EdgeIP string
}

func NewWSClient(parentCtx context.Context, config *WsConfig, logger *logrus.Logger) *WsTransport {
Expand Down Expand Up @@ -127,7 +128,7 @@ func (c *WsTransport) channelDialer() {
case <-c.ctx.Done():
return
default:
tunnelWSConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, "/channel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
tunnelWSConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, c.config.EdgeIP, "/channel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
if err != nil {
c.logger.Errorf("control channel dialer: %v", err)
time.Sleep(c.config.RetryInterval)
Expand Down Expand Up @@ -284,7 +285,7 @@ func (c *WsTransport) tunnelDialer() {
c.logger.Debugf("initiating new websocket tunnel connection to address %s", c.config.RemoteAddr)

// Dial to the tunnel server
tunnelConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, "/tunnel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
tunnelConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, c.config.EdgeIP, "/tunnel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
if err != nil {
c.logger.Errorf("tunnel server dialer: %v", err)

Expand Down
5 changes: 3 additions & 2 deletions internal/client/transport/wsmux.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type WsMuxConfig struct {
WebPort int
Mode config.TransportType
AggressivePool bool
EdgeIP string
}

func NewWSMuxClient(parentCtx context.Context, config *WsMuxConfig, logger *logrus.Logger) *WsMuxTransport {
Expand Down Expand Up @@ -140,7 +141,7 @@ func (c *WsMuxTransport) channelDialer() {
return
default:

tunnelWSConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, "/channel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
tunnelWSConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, c.config.EdgeIP, "/channel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
if err != nil {
c.logger.Errorf("control channel dialer: %v", err)
time.Sleep(c.config.RetryInterval)
Expand Down Expand Up @@ -295,7 +296,7 @@ func (c *WsMuxTransport) tunnelDialer() {
c.logger.Debugf("initiating new %s tunnel connection to address %s", c.config.Mode, c.config.RemoteAddr)

// Dial to the tunnel server
tunnelWSConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, "/tunnel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
tunnelWSConn, err := WebSocketDialer(c.ctx, c.config.RemoteAddr, c.config.EdgeIP, "/tunnel", c.config.DialTimeOut, c.config.KeepAlive, c.config.Nodelay, c.config.Token, c.config.Mode, 3)
if err != nil {
c.logger.Errorf("tunnel server dialer: %v", err)

Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type ClientConfig struct {
SnifferLog string `toml:"sniffer_log"`
DialTimeout int `toml:"dial_timeout"`
AggressivePool bool `toml:"aggressive_pool"`
EdgeIP string `toml:"edge_ip"`
}

// Config represents the complete configuration, including both server and client settings.
Expand Down

0 comments on commit 5ebd7ac

Please sign in to comment.