Files
go-meta-listener/mirror/header.go

101 lines
3.0 KiB
Go
Raw Normal View History

package mirror
import (
"bufio"
"bytes"
2025-05-05 15:33:09 -04:00
"crypto/tls"
"io"
"net"
"net/http"
"time"
)
// AddHeaders adds headers to the connection.
// It takes a net.Conn and a map of headers as input.
// It only adds headers if the connection is an HTTP connection.
// It returns a net.Conn with the headers added.
func AddHeaders(conn net.Conn, headers map[string]string) net.Conn {
// Create a buffer to store the original request
var buf bytes.Buffer
teeReader := io.TeeReader(conn, &buf)
// Try to read the request, but also save it to our buffer
req, err := http.ReadRequest(bufio.NewReader(teeReader))
if err != nil {
// Not an HTTP request or couldn't parse, return original connection
return conn
}
// Add our headers
for key, value := range headers {
req.Header.Add(key, value)
}
// Create a pipe to connect our modified request with the output
pr, pw := io.Pipe()
// Write the modified request to one end of the pipe
go func() {
req.Write(pw)
// Then copy the rest of the original connection
io.Copy(pw, conn)
pw.Close()
}()
// Return a ReadWriter that reads from our pipe and writes to the original connection
return &readWriteConn{
Reader: pr,
Writer: conn,
conn: conn,
}
}
// readWriteConn implements net.Conn
type readWriteConn struct {
io.Reader
io.Writer
conn net.Conn
}
// Implement the rest of net.Conn interface by delegating to the original connection
func (rwc *readWriteConn) Close() error { return rwc.conn.Close() }
func (rwc *readWriteConn) LocalAddr() net.Addr { return rwc.conn.LocalAddr() }
func (rwc *readWriteConn) RemoteAddr() net.Addr { return rwc.conn.RemoteAddr() }
func (rwc *readWriteConn) SetDeadline(t time.Time) error { return rwc.conn.SetDeadline(t) }
func (rwc *readWriteConn) SetReadDeadline(t time.Time) error { return rwc.conn.SetReadDeadline(t) }
func (rwc *readWriteConn) SetWriteDeadline(t time.Time) error { return rwc.conn.SetWriteDeadline(t) }
// Accept accepts a connection from the listener.
// It takes a net.Listener as input and returns a net.Conn with the headers added.
// It is used to accept connections from the meta listener and add headers to them.
func (ml *Mirror) Accept() (net.Conn, error) {
// Accept a connection from the listener
conn, err := ml.MetaListener.Accept()
if err != nil {
2025-05-05 15:33:09 -04:00
log.Println("Error accepting connection:", err)
return nil, err
}
2025-05-05 15:33:09 -04:00
// Check if the connection is a TLS connection
if tlsConn, ok := conn.(*tls.Conn); ok {
// If it is a TLS connection, perform the handshake
if err := tlsConn.Handshake(); err != nil {
log.Println("Error performing TLS handshake:", err)
return nil, err
}
// If the handshake is successful, get the underlying connection
2025-05-26 18:18:10 -04:00
// conn = tlsConn.NetConn()
2025-05-05 15:33:09 -04:00
}
host := map[string]string{
2025-05-21 13:01:31 -04:00
"Host": conn.LocalAddr().String(),
"X-Forwarded-For": conn.RemoteAddr().String(),
"X-Forwarded-Proto": "http",
}
2025-05-05 15:33:09 -04:00
// Add headers to the connection
conn = AddHeaders(conn, host)
return conn, nil
}