upnp.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package upnp
  2. import (
  3. "errors"
  4. "log"
  5. "sync"
  6. "time"
  7. "gitlab.com/NebulousLabs/go-upnp"
  8. )
  9. /*
  10. uPNP Module
  11. This module handles uPNP Connections to the gateway router and create a port forward entry
  12. for the host system at the given port (set with -port paramter)
  13. */
  14. type UPnPClient struct {
  15. Connection *upnp.IGD //UPnP conenction object
  16. ExternalIP string //Storage of external IP address
  17. RequiredPorts []int //All the required ports will be recored
  18. PolicyNames sync.Map //Name for the required port nubmer
  19. RenewStopChan chan bool
  20. }
  21. func NewUPNPClient() (*UPnPClient, error) {
  22. //Create uPNP forwarding in the NAT router
  23. log.Println("Discovering UPnP router in Local Area Network...")
  24. d, err := upnp.Discover()
  25. if err != nil {
  26. return &UPnPClient{}, err
  27. }
  28. // discover external IP
  29. ip, err := d.ExternalIP()
  30. if err != nil {
  31. return &UPnPClient{}, err
  32. }
  33. //Create the final obejcts
  34. ticker := time.NewTicker(6 * time.Hour)
  35. stop := make(chan bool)
  36. newUPnPObject := &UPnPClient{
  37. Connection: d,
  38. ExternalIP: ip,
  39. RequiredPorts: []int{},
  40. RenewStopChan: stop,
  41. }
  42. go func() {
  43. defer ticker.Stop()
  44. for {
  45. select {
  46. case <-stop:
  47. return
  48. case <-ticker.C:
  49. newUPnPObject.RenewForwardRules()
  50. }
  51. }
  52. }()
  53. return newUPnPObject, nil
  54. }
  55. func (u *UPnPClient) ForwardPort(portNumber int, ruleName string) error {
  56. log.Println("UPnP forwarding new port: ", portNumber, "for "+ruleName+" service")
  57. //Check if port already forwarded
  58. _, ok := u.PolicyNames.Load(portNumber)
  59. if ok {
  60. //Port already forward. Ignore this request
  61. return errors.New("Port already forwarded")
  62. }
  63. // forward a port
  64. err := u.Connection.Forward(uint16(portNumber), ruleName)
  65. if err != nil {
  66. return err
  67. }
  68. u.RequiredPorts = append(u.RequiredPorts, portNumber)
  69. u.PolicyNames.Store(portNumber, ruleName)
  70. return nil
  71. }
  72. func (u *UPnPClient) ClosePort(portNumber int) error {
  73. //Check if port is opened
  74. portOpened := false
  75. newRequiredPort := []int{}
  76. for _, thisPort := range u.RequiredPorts {
  77. if thisPort != portNumber {
  78. newRequiredPort = append(newRequiredPort, thisPort)
  79. } else {
  80. portOpened = true
  81. }
  82. }
  83. if portOpened {
  84. //Update the port list
  85. u.RequiredPorts = newRequiredPort
  86. // Close the port
  87. log.Println("Closing UPnP Port Forward: ", portNumber)
  88. err := u.Connection.Clear(uint16(portNumber))
  89. //Delete the name registry
  90. u.PolicyNames.Delete(portNumber)
  91. if err != nil {
  92. log.Println(err)
  93. return err
  94. }
  95. }
  96. return nil
  97. }
  98. // Renew forward rules, prevent router lease time from flushing the Upnp config
  99. func (u *UPnPClient) RenewForwardRules() {
  100. portsToRenew := u.RequiredPorts
  101. for _, thisPort := range portsToRenew {
  102. ruleName, ok := u.PolicyNames.Load(thisPort)
  103. if !ok {
  104. continue
  105. }
  106. u.ClosePort(thisPort)
  107. time.Sleep(100 * time.Millisecond)
  108. u.ForwardPort(thisPort, ruleName.(string))
  109. }
  110. log.Println("UPnP Port Forward rule renew completed")
  111. }
  112. func (u *UPnPClient) Close() {
  113. //Shutdown the default UPnP Object
  114. if u != nil {
  115. if u.RenewStopChan != nil {
  116. u.RenewStopChan <- true
  117. }
  118. for _, portNumber := range u.RequiredPorts {
  119. err := u.Connection.Clear(uint16(portNumber))
  120. if err != nil {
  121. log.Println(err)
  122. }
  123. }
  124. }
  125. }