network.forward.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package main
  2. import (
  3. "encoding/json"
  4. "log"
  5. "net/http"
  6. "strconv"
  7. "imuslab.com/arozos/mod/common"
  8. prout "imuslab.com/arozos/mod/prouter"
  9. )
  10. /*
  11. Network Forward Interface
  12. author: tobychui
  13. This is an interface for providing a web UI for port forwarding to this host
  14. on different ports. Useful if you need to forward alternative ports for your
  15. services.
  16. */
  17. func portForwardInit() {
  18. //Create database table if not exists
  19. sysdb.NewTable("portforward")
  20. //Register modules
  21. if *allow_upnp {
  22. //Forward the previous registered paths
  23. entries, _ := sysdb.ListTable("portforward")
  24. for _, keypairs := range entries {
  25. portNumber, _ := strconv.Atoi(string(keypairs[0]))
  26. policyName := "Unknown Forward Rule"
  27. json.Unmarshal(keypairs[1], &policyName)
  28. //Forward the recorded port
  29. err := UPNP.ForwardPort(portNumber, policyName)
  30. if err != nil {
  31. log.Println("Port Fordware Failed: ", err.Error(), ". Skipping "+policyName)
  32. }
  33. }
  34. //Create a setting interface for port forward
  35. router := prout.NewModuleRouter(prout.RouterOption{
  36. ModuleName: "System Setting",
  37. AdminOnly: false,
  38. UserHandler: userHandler,
  39. DeniedHandler: func(w http.ResponseWriter, r *http.Request) {
  40. common.SendErrorResponse(w, "Permission Denied")
  41. },
  42. })
  43. registerSetting(settingModule{
  44. Name: "Port Forward",
  45. Desc: "UPnP based port forwarding",
  46. IconPath: "SystemAO/network/img/portforward.png",
  47. Group: "Network",
  48. StartDir: "SystemAO/network/portforward.html",
  49. })
  50. router.HandleFunc("/system/network/portforward", portforward_handleForward)
  51. }
  52. }
  53. func portforward_handleForward(w http.ResponseWriter, r *http.Request) {
  54. opr, _ := common.Mv(r, "opr", true)
  55. if opr == "" {
  56. if UPNP == nil {
  57. common.SendErrorResponse(w, "UPNP is not enabled")
  58. return
  59. }
  60. //List the current forward port and names
  61. type register struct {
  62. Port int
  63. Name string
  64. ReadOnly bool
  65. }
  66. forwardPorts := []register{}
  67. for _, port := range UPNP.RequiredPorts {
  68. //Get the name of the policy
  69. name, ok := UPNP.PolicyNames.Load(port)
  70. if !ok {
  71. name = "Unknown Service"
  72. }
  73. readOnly := false
  74. if port == *listen_port {
  75. //This is the port where the webUI is hosted. No change allowed
  76. readOnly = true
  77. }
  78. thisPort := register{
  79. Port: port,
  80. Name: name.(string),
  81. ReadOnly: readOnly,
  82. }
  83. //log.Println(thisPort)
  84. forwardPorts = append(forwardPorts, thisPort)
  85. }
  86. //Send the result as json
  87. js, _ := json.Marshal(forwardPorts)
  88. common.SendJSONResponse(w, string(js))
  89. } else if opr == "add" {
  90. port, err := common.Mv(r, "port", true)
  91. if err != nil {
  92. common.SendErrorResponse(w, "Invalid port number")
  93. return
  94. }
  95. //Convert port to int
  96. portNumberic, err := strconv.Atoi(port)
  97. if err != nil {
  98. common.SendErrorResponse(w, "Invalid port number")
  99. return
  100. }
  101. //Get the policy name
  102. policyName, err := common.Mv(r, "name", true)
  103. if err != nil {
  104. policyName = "Unnamed Forward Policy"
  105. }
  106. //Write port forward rules to database
  107. sysdb.Write("portforward", strconv.Itoa(portNumberic), policyName)
  108. if UPNP != nil {
  109. //Forward the port
  110. err := UPNP.ForwardPort(portNumberic, policyName)
  111. if err != nil {
  112. common.SendErrorResponse(w, err.Error())
  113. } else {
  114. common.SendOK(w)
  115. }
  116. } else {
  117. common.SendErrorResponse(w, "UPNP is not enabled")
  118. return
  119. }
  120. } else if opr == "remove" {
  121. port, err := common.Mv(r, "port", true)
  122. if err != nil {
  123. common.SendErrorResponse(w, "Invalid port number")
  124. return
  125. }
  126. //Convert port to int
  127. portNumberic, err := strconv.Atoi(port)
  128. if err != nil {
  129. common.SendErrorResponse(w, "Invalid port number")
  130. return
  131. }
  132. //Remove it from db if exists
  133. if sysdb.KeyExists("portforward", strconv.Itoa(portNumberic)) {
  134. //Key exists. Remove it from db
  135. sysdb.Delete("portforward", strconv.Itoa(portNumberic))
  136. }
  137. if UPNP != nil {
  138. err := UPNP.ClosePort(portNumberic)
  139. if err != nil {
  140. common.SendErrorResponse(w, err.Error())
  141. } else {
  142. common.SendOK(w)
  143. }
  144. } else {
  145. common.SendErrorResponse(w, "UPNP is not enabled")
  146. return
  147. }
  148. }
  149. }