英文:
Intercept tls.Conn's Read() and Write() while retaining tls.Conn functionality
问题
我有以下一段代码:
l, err := tls.Listen("tcp", "localhost:0", cfg)
dieIf(err)
c, err := l.Accept()
dieIf(err)
err = c.(*tls.Conn).Handshake()
dieIf(err)
它运行得很好,但我想拦截tls.Conn的读写操作。
我考虑过这样做:
type MitmConn struct {
  net.Conn
}
func (self *MitmConn) Read(b []byte) (n int, err error) {
  ...
}
func (self *MitmConn) Write(b []byte) (n int, err error) {
  ...
}
l, err := tls.Listen("tcp", "localhost:0", cfg)
dieIf(err)
c, err := l.Accept()
dieIf(err)
c = &MitmConn{c}
但是,接下来会出错:
// panic: interface conversion: net.Conn is *MitmConn, not *tls.Conn
err = c.(*tls.Conn).Handshake()
dieIf(err)
有什么想法吗?
英文:
I have the following piece of code:
l, err := tls.Listen("tcp", "localhost:0", cfg)
dieIf(err)
c, err := l.Accept()
dieIf(err)
err = c.(*tls.Conn).Handshake()
dieIf(err)
It works just fine, but I'd like to intercept tls.Conn's reads and writes.
I thought about doing this:
type MitmConn struct {
  net.Conn
}
func (self *MitmConn) Read(b []byte) (n int, err error) {
  ...
}
func (self *MitmConn) Write(b []byte) (n int, err error) {
  ...
}
l, err := tls.Listen("tcp", "localhost:0", cfg)
dieIf(err)
c, err := l.Accept()
dieIf(err)
c = &MitmConn{c}
But then, this would fail:
// panic: interface conversion: net.Conn is *MitmConn, not *tls.Conn
err = c.(*tls.Conn).Handshake()
dieIf(err)
Any ideas?
答案1
得分: 2
package main
import "crypto/tls"
func dieIf(err error) {
	if err != nil {
		panic(err)
	}
}
type mitmConn struct {
	*tls.Conn
}
func (mc *mitmConn) Read(b []byte) (n int, err error) {
	return 0, nil
}
func (mc *mitmConn) Write(b []byte) (n int, err error) {
	return 0, nil
}
func main() {
	l, err := tls.Listen("tcp", "localhost:0", nil)
	dieIf(err)
	c, err := l.Accept()
	dieIf(err)
	mc := mitmConn{c.(*tls.Conn)}
	err = mc.Handshake()
	dieIf(err)
}
请考虑不要使用self作为接收器的命名(还有这个)。
英文:
package main
import "crypto/tls"
func dieIf(err error) {
	if err != nil {
		panic(err)
	}
}
type mitmConn struct {
	*tls.Conn
}
func (mc *mitmConn) Read(b []byte) (n int, err error) {
  return 0, nil
}
func (mc *mitmConn) Write(b []byte) (n int, err error) {
  return 0, nil
}
func main() {
	l, err := tls.Listen("tcp", "localhost:0", nil)
	dieIf(err)
	c, err := l.Accept()
	dieIf(err)
	mc := mitmConn{c.(*tls.Conn)}
	err = mc.Handshake()
	dieIf(err)
}
Please consider unlearning naming the receivers self (and also this).
答案2
得分: 0
@kostix的答案对大多数情况已经足够了,但如果你想拦截tls.Conn.Handshake()的读写操作,你需要在更低一级注入你的mitmConn包装器。
这是一个可行的示例:
package main
import "crypto/tls"
func dieIf(err error) {
    if err != nil {
        panic(err)
    }
}
type mitmConn struct {
    // 由于我们在更低一级,这里不需要 *tls.Conn
    net.Conn
}
func (mc *mitmConn) Read(b []byte) (n int, err error) {
  return 0, nil
}
func (mc *mitmConn) Write(b []byte) (n int, err error) {
  return 0, nil
}
func main() {
    // 不要使用 tls.Listen
    l, err := net.Listen("tcp", "localhost:0")
    dieIf(err)
    c, err := l.Accept()
    dieIf(err)
    // 创建一个新的 tls.Conn。
    // 在 tls.Server() 调用之后,Conn 对象的嵌套关系如下:
    // - *tls.Conn
    //  - mitmConn
    //   - *net.TCPConn
    c = tls.Server(mitmConn{c}, nil)
    // 由于 tls.Server 返回的是 net.Conn,而不是 *tls.Conn,我们需要进行类型转换
    err = c.(*tls.Conn).Handshake()
    dieIf(err)
}
英文:
@kostix's answer suffices for most cases, but if you want to intercept tls.Conn.Handshake()'s reads and writes, you need to inject your mitmConn wrapper one level beneath.
Here's a working example:
package main
import "crypto/tls"
func dieIf(err error) {
    if err != nil {
        panic(err)
    }
}
type mitmConn struct {
    // Since we went one level beneath, no need for *tls.Conn here
    net.Conn
}
func (mc *mitmConn) Read(b []byte) (n int, err error) {
  return 0, nil
}
func (mc *mitmConn) Write(b []byte) (n int, err error) {
  return 0, nil
}
func main() {
    // Don't use tls.Listen
    l, err := net.Listen("tcp", "localhost:0")
    dieIf(err)
    c, err := l.Accept()
    dieIf(err)
    // Make a new tls.Conn. 
    // After the tls.Server() call, the nesting of Conn 
    // objects looks will be:
    // - *tls.Conn
    //  - mitmConn
    //   - *net.TCPConn
    c = tls.Server(mitmConn{c}, nil)
    // Since tls.Server returns a net.Conn, not a *tls.Conn, we need to cast
    err = c.(*tls.Conn).Handshake()
    dieIf(err)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论