拦截tls.Conn的Read()和Write()方法,同时保留tls.Conn的功能。

huangapple go评论114阅读模式
英文:

Intercept tls.Conn's Read() and Write() while retaining tls.Conn functionality

问题

我有以下一段代码:

  1. l, err := tls.Listen("tcp", "localhost:0", cfg)
  2. dieIf(err)
  3. c, err := l.Accept()
  4. dieIf(err)
  5. err = c.(*tls.Conn).Handshake()
  6. dieIf(err)

它运行得很好,但我想拦截tls.Conn的读写操作。

我考虑过这样做:

  1. type MitmConn struct {
  2. net.Conn
  3. }
  4. func (self *MitmConn) Read(b []byte) (n int, err error) {
  5. ...
  6. }
  7. func (self *MitmConn) Write(b []byte) (n int, err error) {
  8. ...
  9. }
  10. l, err := tls.Listen("tcp", "localhost:0", cfg)
  11. dieIf(err)
  12. c, err := l.Accept()
  13. dieIf(err)
  14. c = &MitmConn{c}

但是,接下来会出错:

  1. // panic: interface conversion: net.Conn is *MitmConn, not *tls.Conn
  2. err = c.(*tls.Conn).Handshake()
  3. dieIf(err)

有什么想法吗?

英文:

I have the following piece of code:

  1. l, err := tls.Listen("tcp", "localhost:0", cfg)
  2. dieIf(err)
  3. c, err := l.Accept()
  4. dieIf(err)
  5. err = c.(*tls.Conn).Handshake()
  6. dieIf(err)

It works just fine, but I'd like to intercept tls.Conn's reads and writes.

I thought about doing this:

  1. type MitmConn struct {
  2. net.Conn
  3. }
  4. func (self *MitmConn) Read(b []byte) (n int, err error) {
  5. ...
  6. }
  7. func (self *MitmConn) Write(b []byte) (n int, err error) {
  8. ...
  9. }
  10. l, err := tls.Listen("tcp", "localhost:0", cfg)
  11. dieIf(err)
  12. c, err := l.Accept()
  13. dieIf(err)
  14. c = &MitmConn{c}

But then, this would fail:

  1. // panic: interface conversion: net.Conn is *MitmConn, not *tls.Conn
  2. err = c.(*tls.Conn).Handshake()
  3. dieIf(err)

Any ideas?

答案1

得分: 2

  1. package main
  2. import "crypto/tls"
  3. func dieIf(err error) {
  4. if err != nil {
  5. panic(err)
  6. }
  7. }
  8. type mitmConn struct {
  9. *tls.Conn
  10. }
  11. func (mc *mitmConn) Read(b []byte) (n int, err error) {
  12. return 0, nil
  13. }
  14. func (mc *mitmConn) Write(b []byte) (n int, err error) {
  15. return 0, nil
  16. }
  17. func main() {
  18. l, err := tls.Listen("tcp", "localhost:0", nil)
  19. dieIf(err)
  20. c, err := l.Accept()
  21. dieIf(err)
  22. mc := mitmConn{c.(*tls.Conn)}
  23. err = mc.Handshake()
  24. dieIf(err)
  25. }

考虑不要使用self作为接收器的命名(还有这个)。

英文:
  1. package main
  2. import "crypto/tls"
  3. func dieIf(err error) {
  4. if err != nil {
  5. panic(err)
  6. }
  7. }
  8. type mitmConn struct {
  9. *tls.Conn
  10. }
  11. func (mc *mitmConn) Read(b []byte) (n int, err error) {
  12. return 0, nil
  13. }
  14. func (mc *mitmConn) Write(b []byte) (n int, err error) {
  15. return 0, nil
  16. }
  17. func main() {
  18. l, err := tls.Listen("tcp", "localhost:0", nil)
  19. dieIf(err)
  20. c, err := l.Accept()
  21. dieIf(err)
  22. mc := mitmConn{c.(*tls.Conn)}
  23. err = mc.Handshake()
  24. dieIf(err)
  25. }

Please consider unlearning naming the receivers self (and also this).

答案2

得分: 0

@kostix的答案对大多数情况已经足够了,但如果你想拦截tls.Conn.Handshake()的读写操作,你需要在更低一级注入你的mitmConn包装器。

这是一个可行的示例:

  1. package main
  2. import "crypto/tls"
  3. func dieIf(err error) {
  4. if err != nil {
  5. panic(err)
  6. }
  7. }
  8. type mitmConn struct {
  9. // 由于我们在更低一级,这里不需要 *tls.Conn
  10. net.Conn
  11. }
  12. func (mc *mitmConn) Read(b []byte) (n int, err error) {
  13. return 0, nil
  14. }
  15. func (mc *mitmConn) Write(b []byte) (n int, err error) {
  16. return 0, nil
  17. }
  18. func main() {
  19. // 不要使用 tls.Listen
  20. l, err := net.Listen("tcp", "localhost:0")
  21. dieIf(err)
  22. c, err := l.Accept()
  23. dieIf(err)
  24. // 创建一个新的 tls.Conn。
  25. // 在 tls.Server() 调用之后,Conn 对象的嵌套关系如下:
  26. // - *tls.Conn
  27. // - mitmConn
  28. // - *net.TCPConn
  29. c = tls.Server(mitmConn{c}, nil)
  30. // 由于 tls.Server 返回的是 net.Conn,而不是 *tls.Conn,我们需要进行类型转换
  31. err = c.(*tls.Conn).Handshake()
  32. dieIf(err)
  33. }
英文:

@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:

  1. package main
  2. import "crypto/tls"
  3. func dieIf(err error) {
  4. if err != nil {
  5. panic(err)
  6. }
  7. }
  8. type mitmConn struct {
  9. // Since we went one level beneath, no need for *tls.Conn here
  10. net.Conn
  11. }
  12. func (mc *mitmConn) Read(b []byte) (n int, err error) {
  13. return 0, nil
  14. }
  15. func (mc *mitmConn) Write(b []byte) (n int, err error) {
  16. return 0, nil
  17. }
  18. func main() {
  19. // Don't use tls.Listen
  20. l, err := net.Listen("tcp", "localhost:0")
  21. dieIf(err)
  22. c, err := l.Accept()
  23. dieIf(err)
  24. // Make a new tls.Conn.
  25. // After the tls.Server() call, the nesting of Conn
  26. // objects looks will be:
  27. // - *tls.Conn
  28. // - mitmConn
  29. // - *net.TCPConn
  30. c = tls.Server(mitmConn{c}, nil)
  31. // Since tls.Server returns a net.Conn, not a *tls.Conn, we need to cast
  32. err = c.(*tls.Conn).Handshake()
  33. dieIf(err)
  34. }

huangapple
  • 本文由 发表于 2021年9月29日 01:41:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/69366260.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定