proxy.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package portmapper
  2. import (
  3. "fmt"
  4. "io"
  5. "net"
  6. "github.com/ishidawataru/sctp"
  7. )
  8. type userlandProxy interface {
  9. Start() error
  10. Stop() error
  11. }
  12. // ipVersion refers to IP version - v4 or v6
  13. type ipVersion string
  14. const (
  15. // IPv4 is version 4
  16. ipv4 ipVersion = "4"
  17. // IPv4 is version 6
  18. ipv6 ipVersion = "6"
  19. )
  20. // dummyProxy just listen on some port, it is needed to prevent accidental
  21. // port allocations on bound port, because without userland proxy we using
  22. // iptables rules and not net.Listen
  23. type dummyProxy struct {
  24. listener io.Closer
  25. addr net.Addr
  26. ipVersion ipVersion
  27. }
  28. func newDummyProxy(proto string, hostIP net.IP, hostPort int) (userlandProxy, error) {
  29. // detect version of hostIP to bind only to correct version
  30. version := ipv4
  31. if hostIP.To4() == nil {
  32. version = ipv6
  33. }
  34. switch proto {
  35. case "tcp":
  36. addr := &net.TCPAddr{IP: hostIP, Port: hostPort}
  37. return &dummyProxy{addr: addr, ipVersion: version}, nil
  38. case "udp":
  39. addr := &net.UDPAddr{IP: hostIP, Port: hostPort}
  40. return &dummyProxy{addr: addr, ipVersion: version}, nil
  41. case "sctp":
  42. addr := &sctp.SCTPAddr{IPAddrs: []net.IPAddr{{IP: hostIP}}, Port: hostPort}
  43. return &dummyProxy{addr: addr, ipVersion: version}, nil
  44. default:
  45. return nil, fmt.Errorf("Unknown addr type: %s", proto)
  46. }
  47. }
  48. func (p *dummyProxy) Start() error {
  49. switch addr := p.addr.(type) {
  50. case *net.TCPAddr:
  51. l, err := net.ListenTCP("tcp"+string(p.ipVersion), addr)
  52. if err != nil {
  53. return err
  54. }
  55. p.listener = l
  56. case *net.UDPAddr:
  57. l, err := net.ListenUDP("udp"+string(p.ipVersion), addr)
  58. if err != nil {
  59. return err
  60. }
  61. p.listener = l
  62. case *sctp.SCTPAddr:
  63. l, err := sctp.ListenSCTP("sctp"+string(p.ipVersion), addr)
  64. if err != nil {
  65. return err
  66. }
  67. p.listener = l
  68. default:
  69. return fmt.Errorf("Unknown addr type: %T", p.addr)
  70. }
  71. return nil
  72. }
  73. func (p *dummyProxy) Stop() error {
  74. if p.listener != nil {
  75. return p.listener.Close()
  76. }
  77. return nil
  78. }