net.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package ovpm
  2. import (
  3. "fmt"
  4. "net"
  5. "github.com/Sirupsen/logrus"
  6. "github.com/coreos/go-iptables/iptables"
  7. )
  8. // routedInterface returns a network interface that can route IP
  9. // traffic and satisfies flags. It returns nil when an appropriate
  10. // network interface is not found. Network must be "ip", "ip4" or
  11. // "ip6".
  12. func routedInterface(network string, flags net.Flags) *net.Interface {
  13. switch network {
  14. case "ip", "ip4", "ip6":
  15. default:
  16. return nil
  17. }
  18. ift, err := net.Interfaces()
  19. if err != nil {
  20. return nil
  21. }
  22. for _, ifi := range ift {
  23. if ifi.Flags&flags != flags {
  24. continue
  25. }
  26. if _, ok := hasRoutableIP(network, &ifi); !ok {
  27. continue
  28. }
  29. return &ifi
  30. }
  31. return nil
  32. }
  33. func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) {
  34. ifat, err := ifi.Addrs()
  35. if err != nil {
  36. return nil, false
  37. }
  38. for _, ifa := range ifat {
  39. switch ifa := ifa.(type) {
  40. case *net.IPAddr:
  41. if ip := routableIP(network, ifa.IP); ip != nil {
  42. return ip, true
  43. }
  44. case *net.IPNet:
  45. if ip := routableIP(network, ifa.IP); ip != nil {
  46. return ip, true
  47. }
  48. }
  49. }
  50. return nil, false
  51. }
  52. func vpnInterface() *net.Interface {
  53. mask := net.IPMask(net.ParseIP(_DefaultServerNetMask))
  54. prefix := net.ParseIP(_DefaultServerNetwork)
  55. netw := prefix.Mask(mask).To4()
  56. netw[3] = byte(1) // Server is always gets xxx.xxx.xxx.1
  57. ipnet := net.IPNet{IP: netw, Mask: mask}
  58. ifs, err := net.Interfaces()
  59. if err != nil {
  60. logrus.Errorf("can not get system network interfaces: %v", err)
  61. return nil
  62. }
  63. for _, ifc := range ifs {
  64. addrs, err := ifc.Addrs()
  65. if err != nil {
  66. logrus.Errorf("can not get interface addresses: %v", err)
  67. return nil
  68. }
  69. for _, addr := range addrs {
  70. //logrus.Debugf("addr: %s == %s", addr.String(), ipnet.String())
  71. if addr.String() == ipnet.String() {
  72. return &ifc
  73. }
  74. }
  75. }
  76. return nil
  77. }
  78. func routableIP(network string, ip net.IP) net.IP {
  79. if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() {
  80. return nil
  81. }
  82. switch network {
  83. case "ip4":
  84. if ip := ip.To4(); ip != nil {
  85. return ip
  86. }
  87. case "ip6":
  88. if ip.IsLoopback() { // addressing scope of the loopback address depends on each implementation
  89. return nil
  90. }
  91. if ip := ip.To16(); ip != nil && ip.To4() == nil {
  92. return ip
  93. }
  94. default:
  95. if ip := ip.To4(); ip != nil {
  96. return ip
  97. }
  98. if ip := ip.To16(); ip != nil {
  99. return ip
  100. }
  101. }
  102. return nil
  103. }
  104. // EnsureNatEnabled is an idempotent command that ensures nat is enabled for the vpn server.
  105. func EnsureNatEnabled() error {
  106. rif := routedInterface("ip", net.FlagUp|net.FlagBroadcast)
  107. if rif == nil {
  108. return fmt.Errorf("can not get routable network interface")
  109. }
  110. vpnIfc := vpnInterface()
  111. if vpnIfc == nil {
  112. return fmt.Errorf("can not get vpn network interface on the system")
  113. }
  114. // Enable ip forwarding.
  115. emitToFile("/proc/sys/net/ipv4/ip_forward", "1", 0)
  116. ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4)
  117. if err != nil {
  118. return fmt.Errorf("can not create new iptables object: %v", err)
  119. }
  120. // Append iptables nat rules.
  121. ipt.AppendUnique("nat", "POSTROUTING", "-o", rif.Name, "-j", "MASQUERADE")
  122. // TODO(cad): we should use the interface name that we get when we query the system
  123. // with the vpn server's internal ip address, instead of default "tun0".
  124. ipt.AppendUnique("filter", "FORWARD", "-i", rif.Name, "-o", vpnIfc.Name, "-m", "state", "--state", "RELATED, ESTABLISHED", "-j", "ACCEPT")
  125. ipt.AppendUnique("filter", "FORWARD", "-i", vpnIfc.Name, "-o", rif.Name, "-j", "ACCEPT")
  126. return nil
  127. }