mirror of
https://github.com/fosrl/gerbil.git
synced 2026-03-22 21:29:33 -05:00
Compare commits
1 Commits
dev
...
proxy-perf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7d9c72f29 |
@@ -69,6 +69,12 @@ type SNIProxy struct {
|
|||||||
|
|
||||||
// Trusted upstream proxies that can send PROXY protocol
|
// Trusted upstream proxies that can send PROXY protocol
|
||||||
trustedUpstreams map[string]struct{}
|
trustedUpstreams map[string]struct{}
|
||||||
|
|
||||||
|
// Reusable HTTP client for API requests
|
||||||
|
httpClient *http.Client
|
||||||
|
|
||||||
|
// Buffer pool for connection piping
|
||||||
|
bufferPool *sync.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
type activeTunnel struct {
|
type activeTunnel struct {
|
||||||
@@ -374,6 +380,20 @@ func NewSNIProxy(port int, remoteConfigURL, publicKey, localProxyAddr string, lo
|
|||||||
localOverrides: overridesMap,
|
localOverrides: overridesMap,
|
||||||
activeTunnels: make(map[string]*activeTunnel),
|
activeTunnels: make(map[string]*activeTunnel),
|
||||||
trustedUpstreams: trustedMap,
|
trustedUpstreams: trustedMap,
|
||||||
|
httpClient: &http.Client{
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
MaxIdleConnsPerHost: 10,
|
||||||
|
IdleConnTimeout: 90 * time.Second,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bufferPool: &sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
buf := make([]byte, 32*1024)
|
||||||
|
return &buf
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxy, nil
|
return proxy, nil
|
||||||
@@ -681,9 +701,8 @@ func (p *SNIProxy) getRoute(hostname, clientAddr string) (*RouteRecord, error) {
|
|||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
// Make HTTP request
|
// Make HTTP request using reusable client
|
||||||
client := &http.Client{Timeout: 5 * time.Second}
|
resp, err := p.httpClient.Do(req)
|
||||||
resp, err := client.Do(req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("API request failed: %w", err)
|
return nil, fmt.Errorf("API request failed: %w", err)
|
||||||
}
|
}
|
||||||
@@ -773,9 +792,15 @@ func (p *SNIProxy) pipe(clientConn, targetConn net.Conn, clientReader io.Reader)
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
defer closeConns()
|
defer closeConns()
|
||||||
|
|
||||||
// Use a large buffer for better performance
|
// Get buffer from pool and return when done
|
||||||
buf := make([]byte, 32*1024)
|
bufPtr := p.bufferPool.Get().(*[]byte)
|
||||||
_, err := io.CopyBuffer(targetConn, clientReader, buf)
|
defer func() {
|
||||||
|
// Clear buffer before returning to pool to prevent data leakage
|
||||||
|
clear(*bufPtr)
|
||||||
|
p.bufferPool.Put(bufPtr)
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err := io.CopyBuffer(targetConn, clientReader, *bufPtr)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
logger.Debug("Copy client->target error: %v", err)
|
logger.Debug("Copy client->target error: %v", err)
|
||||||
}
|
}
|
||||||
@@ -786,9 +811,15 @@ func (p *SNIProxy) pipe(clientConn, targetConn net.Conn, clientReader io.Reader)
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
defer closeConns()
|
defer closeConns()
|
||||||
|
|
||||||
// Use a large buffer for better performance
|
// Get buffer from pool and return when done
|
||||||
buf := make([]byte, 32*1024)
|
bufPtr := p.bufferPool.Get().(*[]byte)
|
||||||
_, err := io.CopyBuffer(clientConn, targetConn, buf)
|
defer func() {
|
||||||
|
// Clear buffer before returning to pool to prevent data leakage
|
||||||
|
clear(*bufPtr)
|
||||||
|
p.bufferPool.Put(bufPtr)
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, err := io.CopyBuffer(clientConn, targetConn, *bufPtr)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
logger.Debug("Copy target->client error: %v", err)
|
logger.Debug("Copy target->client error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user