2025-05-01 00:06:51 -04:00
|
|
|
package mirror
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2025-05-21 14:53:34 -04:00
|
|
|
"bytes"
|
2025-05-05 15:33:09 -04:00
|
|
|
"crypto/tls"
|
2025-05-21 14:53:34 -04:00
|
|
|
"io"
|
2025-05-01 00:06:51 -04:00
|
|
|
"net"
|
|
|
|
"net/http"
|
2025-05-21 14:53:34 -04:00
|
|
|
"time"
|
2025-05-01 00:06:51 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// 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 {
|
2025-05-21 14:53:34 -04:00
|
|
|
// 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))
|
2025-05-01 00:06:51 -04:00
|
|
|
if err != nil {
|
2025-05-21 14:53:34 -04:00
|
|
|
// Not an HTTP request or couldn't parse, return original connection
|
2025-05-01 00:06:51 -04:00
|
|
|
return conn
|
|
|
|
}
|
2025-05-21 14:53:34 -04:00
|
|
|
|
|
|
|
// Add our headers
|
2025-05-01 00:06:51 -04:00
|
|
|
for key, value := range headers {
|
|
|
|
req.Header.Add(key, value)
|
|
|
|
}
|
2025-05-21 14:53:34 -04:00
|
|
|
|
|
|
|
// 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,
|
2025-05-01 00:06:51 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-21 14:53:34 -04:00
|
|
|
// 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) }
|
|
|
|
|
2025-05-01 00:06:51 -04:00
|
|
|
// 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)
|
2025-05-01 00:06:51 -04:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2025-05-01 00:06:51 -04:00
|
|
|
host := map[string]string{
|
2025-05-21 13:01:31 -04:00
|
|
|
"Host": conn.LocalAddr().String(),
|
2025-05-01 00:06:51 -04:00
|
|
|
"X-Forwarded-For": conn.RemoteAddr().String(),
|
|
|
|
"X-Forwarded-Proto": "http",
|
|
|
|
}
|
2025-05-05 15:33:09 -04:00
|
|
|
|
2025-05-01 00:06:51 -04:00
|
|
|
// Add headers to the connection
|
|
|
|
conn = AddHeaders(conn, host)
|
|
|
|
|
|
|
|
return conn, nil
|
|
|
|
}
|