Documentation ¶
Overview ¶
Example (MemorizingReader_Memorized) ¶
mr := mitm.NewMemorizingReader(strings.NewReader("Hello, World!"), nil) io.ReadAll(mr) mr.Seek(0, io.SeekStart) fmt.Println(string(mr.Memorized()))
Output: Hello, World!
Example (MemorizingReader_OneTimeReader) ¶
mr := mitm.NewMemorizingReader(strings.NewReader("Hello, World!"), nil) bs, err := mr.Next(5) if err != nil { log.Fatal(err) } fmt.Println(string(bs)) // read from the beginning again without memorizing. if _, err = mr.Seek(0, io.SeekStart); err != nil { log.Fatal(err) } if _, err := io.Copy(os.Stdout, mr.OneTimeReader()); err != nil { log.Fatal(err) }
Output: Hello Hello, World!
Index ¶
- Variables
- func CreateCACert(subject pkix.Name, duration time.Duration) (cert tls.Certificate, err error)
- func CreateCACertPEM(subject pkix.Name, duration time.Duration) (*bytes.Buffer, *bytes.Buffer, error)
- func ForgeCertificate(root *tls.Certificate, orig *x509.Certificate) (tls.Certificate, error)
- func ListenTCPTProxy(network string, laddr *net.TCPAddr) (*net.TCPListener, error)
- func ListenUDPTProxy(network string, laddr *net.UDPAddr) (*net.UDPConn, error)
- func LoadCertificate(certPath, keyPath string) (cert tls.Certificate, err error)
- func NewMemorizingReader(r io.Reader, buf []byte) *memorizingReader
- func NewQUICListener(conn net.PacketConn, config *QUICConfig) (*quicListener, error)
- func NewTLSListener(l net.Listener, config *TLSConfig) (net.Listener, error)
- func NewTLSServer(conn net.Conn, config *TLSConfig) (*tls.Conn, error)
- type Addr
- type OneTimeListener
- type ProxyConn
- type QUICConfig
- type QUICListener
- type ServerInfoCache
- type TLSConfig
- type TamperedConn
- func (c *TamperedConn) Close() (err error)
- func (c *TamperedConn) LocalAddr() net.Addr
- func (c *TamperedConn) Read(b []byte) (int, error)
- func (c *TamperedConn) RemoteAddr() net.Addr
- func (c *TamperedConn) SetDeadline(t time.Time) error
- func (c *TamperedConn) SetReadDeadline(t time.Time) error
- func (c *TamperedConn) SetWriteDeadline(t time.Time) error
- func (c *TamperedConn) Write(b []byte) (int, error)
- type TamperedConnOption
- func TamperConnClose(f func() error) TamperedConnOption
- func TamperConnLocalAddr(f func() net.Addr) TamperedConnOption
- func TamperConnRead(f func(b []byte) (int, error)) TamperedConnOption
- func TamperConnRemoteAddr(f func() net.Addr) TamperedConnOption
- func TamperConnSetDeadline(f func(t time.Time) error) TamperedConnOption
- func TamperConnSetReadDeadline(f func(t time.Time) error) TamperedConnOption
- func TamperConnSetWriteDeadline(f func(t time.Time) error) TamperedConnOption
- func TamperConnWrite(f func(b []byte) (int, error)) TamperedConnOption
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultGetTLSClientConfig = func(serverName string, alpnProtocols []string) *tls.Config { return &tls.Config{ ServerName: serverName, NextProtos: alpnProtocols, } }
var DefaultGetTLSServerConfig = func(certificate *tls.Certificate, negotiatedProtocol string, err error) *tls.Config { config := &tls.Config{} if err != nil { config.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) { return nil, err } return config } if negotiatedProtocol != "" { config.NextProtos = []string{negotiatedProtocol} } if certificate != nil { config.Certificates = []tls.Certificate{*certificate} } return config }
var (
ErrHandshakeWithServer = errors.New("mitm: upstream certificate sniffing failed")
)
var (
ErrInvalidQUICConfig = errors.New("invalid mitm.QUICConfig")
)
var (
ErrInvalidTLSConfig = errors.New("invalid mitm.TLSConfig")
)
Functions ¶
func CreateCACert ¶
func CreateCACertPEM ¶
func ForgeCertificate ¶
func ForgeCertificate(root *tls.Certificate, orig *x509.Certificate) (tls.Certificate, error)
ForgeCertificate creates a new tls.Certificate that looks like the original certificate but signed by the specified root.
func ListenTCPTProxy ¶
func ListenUDPTProxy ¶
func LoadCertificate ¶
func LoadCertificate(certPath, keyPath string) (cert tls.Certificate, err error)
LoadCertificate loads a certificate from the specified files. The returned certificate has the Leaf field set.
func NewMemorizingReader ¶
NewMemorizingReader returns a new memorizingReader.
func NewQUICListener ¶
func NewQUICListener(conn net.PacketConn, config *QUICConfig) (*quicListener, error)
func NewTLSListener ¶
NewTLSListener returns a new net.Listener that listens for incoming TLS connections on l.
Example ¶
rootCACert := mustLoadCACert("root") mitmCACert := mustLoadCACert("mitm") defaultPool := x509.NewCertPool() defaultPool.AddCert(rootCACert.Leaf) mitmPool := x509.NewCertPool() mitmPool.AddCert(mitmCACert.Leaf) // true server l1, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } trueCert := mustIssueLocalCert(rootCACert, "echo") l1 = tls.NewListener(l1, &tls.Config{ Certificates: []tls.Certificate{*trueCert}, }) defer l1.Close() go func() { for { conn, err := l1.Accept() if err != nil { break } go func() { defer conn.Close() io.Copy(conn, conn) // echo }() } }() // MITM server l2, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } l2, err = mitm.NewTLSListener(l2, &mitm.TLSConfig{ RootCertificate: mitmCACert, // self-signed certificate GetClientConfig: func(serverName string, alpnProtocols []string) *tls.Config { c := mitm.DefaultGetTLSClientConfig(serverName, alpnProtocols) c.RootCAs = defaultPool return c }, GetDestination: func(conn net.Conn, serverName string) net.Addr { return l1.Addr() }, }) if err != nil { panic(err) } defer l2.Close() go func() { for { conn, err := l2.Accept() if err != nil { break } go func() { defer conn.Close() io.Copy(os.Stdout, conn) conn.Write([]byte("Bye!\n")) }() } }() clientConn, err := tls.Dial(l2.Addr().Network(), l2.Addr().String(), &tls.Config{ ServerName: "echo", RootCAs: mitmPool, }) if err != nil { panic(err) } defer clientConn.Close() clientConn.Write([]byte("Hello, World!\n")) clientConn.CloseWrite() io.Copy(os.Stdout, clientConn)
Output: Hello, World! Bye!
func NewTLSServer ¶
NewTLSServer returns a new TLS server connection. Unlike tls.Server, this will use a forged certificate to handle the connection as follows:
- Peek the ClientHello message from the connection.
- Sniff the certificate of the upstream server.
- Forge a certificate and returns tls.Server, which will reread the message from the beginning.
Example ¶
rootCACert := mustLoadCACert("root") mitmCACert := mustLoadCACert("mitm") defaultPool := x509.NewCertPool() defaultPool.AddCert(rootCACert.Leaf) mitmPool := x509.NewCertPool() mitmPool.AddCert(mitmCACert.Leaf) // true server l1, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } trueCert := mustIssueLocalCert(rootCACert, "echo") l1 = tls.NewListener(l1, &tls.Config{ Certificates: []tls.Certificate{*trueCert}, }) defer l1.Close() go func() { for { conn, err := l1.Accept() if err != nil { break } go func() { defer conn.Close() io.Copy(conn, conn) // echo }() } }() // MITM server l2, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } defer l2.Close() go func() { for { conn, err := l2.Accept() if err != nil { break } go func() { defer conn.Close() tlsConn, err := mitm.NewTLSServer(conn, &mitm.TLSConfig{ RootCertificate: mitmCACert, // self-signed certificate GetClientConfig: func(serverName string, alpnProtocols []string) *tls.Config { c := mitm.DefaultGetTLSClientConfig(serverName, alpnProtocols) c.RootCAs = defaultPool return c }, GetDestination: func(conn net.Conn, serverName string) net.Addr { return l1.Addr() }, }) if err != nil { return } defer tlsConn.Close() io.Copy(os.Stdout, tlsConn) tlsConn.Write([]byte("Bye!\n")) }() } }() clientConn, err := tls.Dial(l2.Addr().Network(), l2.Addr().String(), &tls.Config{ ServerName: "echo", RootCAs: mitmPool, }) if err != nil { panic(err) } defer clientConn.Close() clientConn.Write([]byte("Hello, World!\n")) clientConn.CloseWrite() io.Copy(os.Stdout, clientConn)
Output: Hello, World! Bye!
Types ¶
type OneTimeListener ¶
type OneTimeListener struct {
// contains filtered or unexported fields
}
OneTimeListener is a net.Listener that accepts only one connection. It is useful when an existing API demands a net.Listener instead of a net.Conn, but you want to serve only one connection. After the first call to [Accept], all subsequent calls will be blocked until [Close] is called.
Example ¶
server, client := net.Pipe() done := make(chan struct{}) sconn := mitm.NewTamperedConn(server, mitm.TamperConnClose(func() error { err := server.Close() close(done) return err })) // when an existing API demands a net.Listener instead of a net.Conn, you can use OneTimeListener. ln := mitm.NewOneTimeListener(sconn) var wg sync.WaitGroup wg.Add(1) go func() { processListener(ln) wg.Done() }() client.Write([]byte("Hello")) client.Close() <-done ln.Close() wg.Wait()
Output: Hello
func NewOneTimeListener ¶
func NewOneTimeListener(conn net.Conn) *OneTimeListener
NewOneTimeListener returns a new OneTimeListener.
func (*OneTimeListener) Accept ¶
func (l *OneTimeListener) Accept() (net.Conn, error)
Accept returns the underlying connection if it has not been accepted yet. Otherwise, it blocks until [Close] is called.
func (*OneTimeListener) Addr ¶
func (l *OneTimeListener) Addr() net.Addr
Addr returns the local network address of the underlying connection.
func (*OneTimeListener) Close ¶
func (l *OneTimeListener) Close() error
Close closes the listener. Any blocked [Accept] calls will be unblocked and return an error.
type ProxyConn ¶
type ProxyConn struct { *TamperedConn // contains filtered or unexported fields }
ProxyConn is a TamperedConn that has a destination address.
func NewProxyConn ¶
NewProxyConn returns a new ProxyConn. dstAddr is the destination address of the connection. opts is used to change the behaviour of the underlying TamperedConn.
func (*ProxyConn) Destination ¶
Destination returns the destination address of the connection.
type QUICConfig ¶
type QUICConfig struct { // RootCertificate is the root certificate to be used to forge certificates. RootCertificate *tls.Certificate // GetDestination specifies a function that returns the destination address of the connection. GetDestination func(conn net.Conn, serverName string) net.Addr // NextProtos is a list of supported ALPN protocols. // If it is empty, the client specified list is used to negotiate the protocol with the actual server. NextProtos []string // TLSServerConfig optionally specifies a tls.Config that is used to handle incoming connections. // That is, the tls.Config is used when the server is acting as a TLS server. TLSServerConfig *tls.Config // GetTLSClientConfig optionally specifies a function that returns a tls.Config that is used to dial the actual server. // That is, the returned tls.Config is used when the server is acting as a TLS client. GetTLSClientConfig func(serverName string, alpnProtocols []string) *tls.Config // ServerConfig optionally specifies a quic.Config that is used to handle incoming connections. ServerConfig *quic.Config // ClientConfig optionally specifies a quic.Config that is used to dial the actual server. ClientConfig *quic.Config // ServerInfoCache optionally specifies a cache that stores the information of the actual servers. // If not set, a new cache is created. ServerInfoCache ServerInfoCache }
func (*QUICConfig) Clone ¶
func (c *QUICConfig) Clone() *QUICConfig
type QUICListener ¶
type ServerInfoCache ¶
type ServerInfoCache map[string]serverInfo
type TLSConfig ¶
type TLSConfig struct { // RootCertificate is the root certificate to be used to forge certificates. RootCertificate *tls.Certificate // GetDestination specifies a function that returns the destination address of the connection. GetDestination func(conn net.Conn, serverName string) net.Addr // NextProtos is a list of supported ALPN protocols. // If it is empty, the client specified list is used to negotiate the protocol with the actual server. NextProtos []string // GetServerConfig optionally specifies a function that returns a tls.Config that is used to handle incoming connections. // That is, the returned tls.Config is used when the server is acting as a TLS server. GetServerConfig func(certificate *tls.Certificate, negotiatedProtocol string, err error) *tls.Config // GetClientConfig optionally specifies a function that returns a tls.Config that is used to dial the actual server. // That is, the returned tls.Config is used when the server is acting as a TLS client. GetClientConfig func(serverName string, alpnProtocols []string) *tls.Config // ServerInfoCache optionally specifies a cache that stores the information of the actual servers. // If not set, a new cache is created. ServerInfoCache ServerInfoCache }
type TamperedConn ¶
type TamperedConn struct {
// contains filtered or unexported fields
}
TamperedConn is a net.Conn that can be tampered. Every net.Conn method can be replaced with a custom implementation.
func NewTamperedConn ¶
func NewTamperedConn(conn net.Conn, opts ...TamperedConnOption) *TamperedConn
NewTamperedConn returns a new TamperedConn. opts is used to change the behaviour of the underlying net.Conn.
Example ¶
server, client := net.Pipe() done := make(chan struct{}) sconn := mitm.NewTamperedConn(server, mitm.TamperConnRead(func(bs []byte) (int, error) { n, err := server.Read(bs) // echo to stdout io.CopyN(os.Stdout, bytes.NewReader(bs), int64(n)) return n, err }), mitm.TamperConnClose(func() error { err := server.Close() close(done) return err })) go func() { defer sconn.Close() io.Copy(io.Discard, sconn) }() client.Write([]byte("Hello, World!\n")) client.Close() <-done
Output: Hello, World!
func (*TamperedConn) Close ¶
func (c *TamperedConn) Close() (err error)
func (*TamperedConn) LocalAddr ¶
func (c *TamperedConn) LocalAddr() net.Addr
func (*TamperedConn) RemoteAddr ¶
func (c *TamperedConn) RemoteAddr() net.Addr
func (*TamperedConn) SetDeadline ¶
func (c *TamperedConn) SetDeadline(t time.Time) error
func (*TamperedConn) SetReadDeadline ¶
func (c *TamperedConn) SetReadDeadline(t time.Time) error
func (*TamperedConn) SetWriteDeadline ¶
func (c *TamperedConn) SetWriteDeadline(t time.Time) error
type TamperedConnOption ¶
type TamperedConnOption func(*TamperedConn) error
func TamperConnClose ¶
func TamperConnClose(f func() error) TamperedConnOption
TamperConnClose replaces the net.Conn.Close method with f.
func TamperConnLocalAddr ¶
func TamperConnLocalAddr(f func() net.Addr) TamperedConnOption
TamperConnLocalAddr replaces the net.Conn.LocalAddr method with f.
func TamperConnRead ¶
func TamperConnRead(f func(b []byte) (int, error)) TamperedConnOption
TamperConnRead replaces the net.Conn.Read method with f.
func TamperConnRemoteAddr ¶
func TamperConnRemoteAddr(f func() net.Addr) TamperedConnOption
TamperConnRemoteAddr replaces the net.Conn.RemoteAddr method with f.
func TamperConnSetDeadline ¶
func TamperConnSetDeadline(f func(t time.Time) error) TamperedConnOption
TamperConnSetDeadline replaces the net.Conn.SetDeadline method with f.
func TamperConnSetReadDeadline ¶
func TamperConnSetReadDeadline(f func(t time.Time) error) TamperedConnOption
TamperConnSetReadDeadline replaces the net.Conn.SetReadDeadline method with f.
func TamperConnSetWriteDeadline ¶
func TamperConnSetWriteDeadline(f func(t time.Time) error) TamperedConnOption
TamperConnSetWriteDeadline replaces the net.Conn.SetWriteDeadline method with f.
func TamperConnWrite ¶
func TamperConnWrite(f func(b []byte) (int, error)) TamperedConnOption
TamperConnWrite replaces the net.Conn.Write method with f.