dialer.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package proxyproto
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "github.com/sagernet/sing-box/adapter"
  7. E "github.com/sagernet/sing/common/exceptions"
  8. M "github.com/sagernet/sing/common/metadata"
  9. N "github.com/sagernet/sing/common/network"
  10. "github.com/pires/go-proxyproto"
  11. )
  12. var _ N.Dialer = (*Dialer)(nil)
  13. type Dialer struct {
  14. N.Dialer
  15. }
  16. func (d *Dialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  17. switch N.NetworkName(network) {
  18. case N.NetworkTCP:
  19. conn, err := d.Dialer.DialContext(ctx, network, destination)
  20. if err != nil {
  21. return nil, err
  22. }
  23. var source M.Socksaddr
  24. metadata := adapter.ContextFrom(ctx)
  25. if metadata != nil {
  26. source = metadata.Source
  27. }
  28. if !source.IsValid() {
  29. source = M.SocksaddrFromNet(conn.LocalAddr())
  30. }
  31. if destination.Addr.Is6() {
  32. source = M.SocksaddrFrom(netip.AddrFrom16(source.Addr.As16()), source.Port)
  33. }
  34. h := proxyproto.HeaderProxyFromAddrs(1, source.TCPAddr(), destination.TCPAddr())
  35. _, err = h.WriteTo(conn)
  36. if err != nil {
  37. conn.Close()
  38. return nil, E.Cause(err, "write proxy protocol header")
  39. }
  40. return conn, nil
  41. default:
  42. return d.Dialer.DialContext(ctx, network, destination)
  43. }
  44. }