1
0

server.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. package server
  2. import (
  3. "errors"
  4. "github.com/cnlh/nps/bridge"
  5. "github.com/cnlh/nps/lib/common"
  6. "github.com/cnlh/nps/lib/file"
  7. "github.com/cnlh/nps/server/proxy"
  8. "github.com/cnlh/nps/server/tool"
  9. "github.com/cnlh/nps/vender/github.com/astaxie/beego"
  10. "github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
  11. "github.com/shirou/gopsutil/cpu"
  12. "github.com/shirou/gopsutil/load"
  13. "github.com/shirou/gopsutil/mem"
  14. "github.com/shirou/gopsutil/net"
  15. "math"
  16. "os"
  17. "strconv"
  18. "strings"
  19. "time"
  20. )
  21. var (
  22. Bridge *bridge.Bridge
  23. RunList map[int]interface{} //运行中的任务
  24. serverStatus []map[string]interface{}
  25. )
  26. func init() {
  27. RunList = make(map[int]interface{})
  28. serverStatus = make([]map[string]interface{}, 0, 1500)
  29. go getSeverStatus()
  30. }
  31. //从csv文件中恢复任务
  32. func InitFromCsv() {
  33. //Add a public password
  34. if vkey := beego.AppConfig.String("public_vkey"); vkey != "" {
  35. c := file.NewClient(vkey, true, true)
  36. file.GetCsvDb().NewClient(c)
  37. RunList[c.Id] = nil
  38. }
  39. //Initialize services in server-side files
  40. file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
  41. if value.(*file.Tunnel).Status {
  42. AddTask(value.(*file.Tunnel))
  43. }
  44. return true
  45. })
  46. }
  47. func DealBridgeTask() {
  48. for {
  49. select {
  50. case t := <-Bridge.OpenTask:
  51. AddTask(t)
  52. case t := <-Bridge.CloseTask:
  53. StopServer(t.Id)
  54. case id := <-Bridge.CloseClient:
  55. DelTunnelAndHostByClientId(id, true)
  56. if v, ok := file.GetCsvDb().Clients.Load(id); ok {
  57. if v.(*file.Client).NoStore {
  58. file.GetCsvDb().DelClient(id)
  59. }
  60. }
  61. case tunnel := <-Bridge.OpenTask:
  62. StartTask(tunnel.Id)
  63. case s := <-Bridge.SecretChan:
  64. logs.Trace("New secret connection, addr", s.Conn.Conn.RemoteAddr())
  65. if t := file.GetCsvDb().GetTaskByMd5Password(s.Password); t != nil {
  66. if !t.Client.GetConn() {
  67. logs.Info("Connections exceed the current client %d limit", t.Client.Id)
  68. s.Conn.Close()
  69. } else if t.Status {
  70. go proxy.NewBaseServer(Bridge, t).DealClient(s.Conn, t.Client, t.Target.TargetStr, nil, common.CONN_TCP, nil, t.Flow)
  71. } else {
  72. s.Conn.Close()
  73. logs.Trace("This key %s cannot be processed,status is close", s.Password)
  74. }
  75. } else {
  76. logs.Trace("This key %s cannot be processed", s.Password)
  77. s.Conn.Close()
  78. }
  79. }
  80. }
  81. }
  82. //start a new server
  83. func StartNewServer(bridgePort int, cnf *file.Tunnel, bridgeType string) {
  84. Bridge = bridge.NewTunnel(bridgePort, bridgeType, common.GetBoolByStr(beego.AppConfig.String("ip_limit")), RunList)
  85. go func() {
  86. if err := Bridge.StartTunnel(); err != nil {
  87. logs.Error("start server bridge error", err)
  88. os.Exit(0)
  89. }
  90. }()
  91. if p, err := beego.AppConfig.Int("p2p_port"); err == nil {
  92. logs.Info("start p2p server port", p)
  93. go proxy.NewP2PServer(p).Start()
  94. }
  95. go DealBridgeTask()
  96. go dealClientFlow()
  97. if svr := NewMode(Bridge, cnf); svr != nil {
  98. if err := svr.Start(); err != nil {
  99. logs.Error(err)
  100. }
  101. RunList[cnf.Id] = svr
  102. } else {
  103. logs.Error("Incorrect startup mode %s", cnf.Mode)
  104. }
  105. }
  106. func dealClientFlow() {
  107. ticker := time.NewTicker(time.Minute)
  108. for {
  109. select {
  110. case <-ticker.C:
  111. dealClientData()
  112. }
  113. }
  114. }
  115. //new a server by mode name
  116. func NewMode(Bridge *bridge.Bridge, c *file.Tunnel) proxy.Service {
  117. var service proxy.Service
  118. switch c.Mode {
  119. case "tcp", "file":
  120. service = proxy.NewTunnelModeServer(proxy.ProcessTunnel, Bridge, c)
  121. case "socks5":
  122. service = proxy.NewSock5ModeServer(Bridge, c)
  123. case "httpProxy":
  124. service = proxy.NewTunnelModeServer(proxy.ProcessHttp, Bridge, c)
  125. case "udp":
  126. service = proxy.NewUdpModeServer(Bridge, c)
  127. case "webServer":
  128. InitFromCsv()
  129. t := &file.Tunnel{
  130. Port: 0,
  131. Mode: "httpHostServer",
  132. Status: true,
  133. }
  134. AddTask(t)
  135. service = proxy.NewWebServer(Bridge)
  136. case "httpHostServer":
  137. service = proxy.NewHttp(Bridge, c)
  138. }
  139. return service
  140. }
  141. //stop server
  142. func StopServer(id int) error {
  143. if v, ok := RunList[id]; ok {
  144. if svr, ok := v.(proxy.Service); ok {
  145. if err := svr.Close(); err != nil {
  146. return err
  147. }
  148. logs.Info("stop server id %d", id)
  149. } else {
  150. logs.Warn("stop server id %d error", id)
  151. }
  152. if t, err := file.GetCsvDb().GetTask(id); err != nil {
  153. return err
  154. } else {
  155. t.Status = false
  156. file.GetCsvDb().UpdateTask(t)
  157. }
  158. delete(RunList, id)
  159. return nil
  160. }
  161. return errors.New("task is not running")
  162. }
  163. //add task
  164. func AddTask(t *file.Tunnel) error {
  165. if t.Mode == "secret" || t.Mode == "p2p" {
  166. logs.Info("secret task %s start ", t.Remark)
  167. RunList[t.Id] = nil
  168. return nil
  169. }
  170. if b := tool.TestServerPort(t.Port, t.Mode); !b && t.Mode != "httpHostServer" {
  171. logs.Error("taskId %d start error port %d open failed", t.Id, t.Port)
  172. return errors.New("the port open error")
  173. }
  174. if minute, err := beego.AppConfig.Int("flow_store_interval"); err == nil && minute > 0 {
  175. go flowSession(time.Minute * time.Duration(minute))
  176. }
  177. if svr := NewMode(Bridge, t); svr != nil {
  178. logs.Info("tunnel task %s start mode:%s port %d", t.Remark, t.Mode, t.Port)
  179. RunList[t.Id] = svr
  180. go func() {
  181. if err := svr.Start(); err != nil {
  182. logs.Error("clientId %d taskId %d start error %s", t.Client.Id, t.Id, err)
  183. delete(RunList, t.Id)
  184. return
  185. }
  186. }()
  187. } else {
  188. return errors.New("the mode is not correct")
  189. }
  190. return nil
  191. }
  192. //start task
  193. func StartTask(id int) error {
  194. if t, err := file.GetCsvDb().GetTask(id); err != nil {
  195. return err
  196. } else {
  197. AddTask(t)
  198. t.Status = true
  199. file.GetCsvDb().UpdateTask(t)
  200. }
  201. return nil
  202. }
  203. //delete task
  204. func DelTask(id int) error {
  205. if _, ok := RunList[id]; ok {
  206. if err := StopServer(id); err != nil {
  207. return err
  208. }
  209. }
  210. return file.GetCsvDb().DelTask(id)
  211. }
  212. //get task list by page num
  213. func GetTunnel(start, length int, typeVal string, clientId int, search string) ([]*file.Tunnel, int) {
  214. list := make([]*file.Tunnel, 0)
  215. var cnt int
  216. keys := file.GetMapKeys(file.GetCsvDb().Tasks, false, "", "")
  217. for _, key := range keys {
  218. if value, ok := file.GetCsvDb().Tasks.Load(key); ok {
  219. v := value.(*file.Tunnel)
  220. if (typeVal != "" && v.Mode != typeVal || (clientId != 0 && v.Client.Id != clientId)) || (typeVal == "" && clientId != v.Client.Id) {
  221. continue
  222. }
  223. if search != "" && !(v.Id == common.GetIntNoErrByStr(search) || v.Port == common.GetIntNoErrByStr(search) || strings.Contains(v.Password, search) || strings.Contains(v.Remark, search)) {
  224. continue
  225. }
  226. cnt++
  227. if _, ok := Bridge.Client.Load(v.Client.Id); ok {
  228. v.Client.IsConnect = true
  229. } else {
  230. v.Client.IsConnect = false
  231. }
  232. if start--; start < 0 {
  233. if length--; length > 0 {
  234. if _, ok := RunList[v.Id]; ok {
  235. v.RunStatus = true
  236. } else {
  237. v.RunStatus = false
  238. }
  239. list = append(list, v)
  240. }
  241. }
  242. }
  243. }
  244. return list, cnt
  245. }
  246. //获取客户端列表
  247. func GetClientList(start, length int, search, sort, order string, clientId int) (list []*file.Client, cnt int) {
  248. list, cnt = file.GetCsvDb().GetClientList(start, length, search, sort, order, clientId)
  249. dealClientData()
  250. return
  251. }
  252. func dealClientData() {
  253. file.GetCsvDb().Clients.Range(func(key, value interface{}) bool {
  254. v := value.(*file.Client)
  255. if _, ok := Bridge.Client.Load(v.Id); ok {
  256. v.IsConnect = true
  257. } else {
  258. v.IsConnect = false
  259. }
  260. v.Flow.InletFlow = 0
  261. v.Flow.ExportFlow = 0
  262. file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
  263. h := value.(*file.Host)
  264. if h.Client.Id == v.Id {
  265. v.Flow.InletFlow += h.Flow.InletFlow
  266. v.Flow.ExportFlow += h.Flow.ExportFlow
  267. }
  268. return true
  269. })
  270. file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
  271. t := value.(*file.Tunnel)
  272. if t.Client.Id == v.Id {
  273. v.Flow.InletFlow += t.Flow.InletFlow
  274. v.Flow.ExportFlow += t.Flow.ExportFlow
  275. }
  276. return true
  277. })
  278. return true
  279. })
  280. return
  281. }
  282. //根据客户端id删除其所属的所有隧道和域名
  283. func DelTunnelAndHostByClientId(clientId int, justDelNoStore bool) {
  284. var ids []int
  285. file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
  286. v := value.(*file.Tunnel)
  287. if justDelNoStore && !v.NoStore {
  288. return true
  289. }
  290. if v.Client.Id == clientId {
  291. ids = append(ids, v.Id)
  292. }
  293. return true
  294. })
  295. for _, id := range ids {
  296. DelTask(id)
  297. }
  298. ids = ids[:0]
  299. file.GetCsvDb().Hosts.Range(func(key, value interface{}) bool {
  300. v := value.(*file.Host)
  301. if justDelNoStore && !v.NoStore {
  302. return true
  303. }
  304. if v.Client.Id == clientId {
  305. ids = append(ids, v.Id)
  306. }
  307. return true
  308. })
  309. for _, id := range ids {
  310. file.GetCsvDb().DelHost(id)
  311. }
  312. }
  313. //关闭客户端连接
  314. func DelClientConnect(clientId int) {
  315. Bridge.DelClient(clientId)
  316. }
  317. func GetDashboardData() map[string]interface{} {
  318. data := make(map[string]interface{})
  319. data["hostCount"] = file.GetCsvDb().GetMapLen(file.GetCsvDb().Hosts)
  320. data["clientCount"] = file.GetCsvDb().GetMapLen(file.GetCsvDb().Clients) - 1 //Remove the public key client
  321. dealClientData()
  322. c := 0
  323. var in, out int64
  324. file.GetCsvDb().Clients.Range(func(key, value interface{}) bool {
  325. v := value.(*file.Client)
  326. if v.IsConnect {
  327. c += 1
  328. }
  329. in += v.Flow.InletFlow
  330. out += v.Flow.ExportFlow
  331. return true
  332. })
  333. data["clientOnlineCount"] = c
  334. data["inletFlowCount"] = int(in)
  335. data["exportFlowCount"] = int(out)
  336. var tcp, udp, secret, socks5, p2p, http int
  337. file.GetCsvDb().Tasks.Range(func(key, value interface{}) bool {
  338. switch value.(*file.Tunnel).Mode {
  339. case "tcp":
  340. tcp += 1
  341. case "socks5":
  342. udp += 1
  343. case "httpProxy":
  344. http += 1
  345. case "udp":
  346. udp += 1
  347. case "p2p":
  348. p2p += 1
  349. case "secret":
  350. secret += 1
  351. }
  352. return true
  353. })
  354. data["tcpC"] = tcp
  355. data["udpCount"] = udp
  356. data["socks5Count"] = socks5
  357. data["httpProxyCount"] = http
  358. data["secretCount"] = secret
  359. data["p2pCount"] = p2p
  360. data["bridgeType"] = beego.AppConfig.String("bridge_type")
  361. data["httpProxyPort"] = beego.AppConfig.String("http_proxy_port")
  362. data["httpsProxyPort"] = beego.AppConfig.String("https_proxy_port")
  363. data["ipLimit"] = beego.AppConfig.String("ip_limit")
  364. data["flowStoreInterval"] = beego.AppConfig.String("flow_store_interval")
  365. data["serverIp"] = beego.AppConfig.String("p2p_ip")
  366. data["p2pPort"] = beego.AppConfig.String("p2p_port")
  367. data["logLevel"] = beego.AppConfig.String("log_level")
  368. tcpCount := 0
  369. file.GetCsvDb().Clients.Range(func(key, value interface{}) bool {
  370. tcpCount += int(value.(*file.Client).NowConn)
  371. return true
  372. })
  373. data["tcpCount"] = tcpCount
  374. cpuPercet, _ := cpu.Percent(0, true)
  375. var cpuAll float64
  376. for _, v := range cpuPercet {
  377. cpuAll += v
  378. }
  379. loads, _ := load.Avg()
  380. data["load"] = loads.String()
  381. data["cpu"] = math.Round(cpuAll / float64(len(cpuPercet)))
  382. swap, _ := mem.SwapMemory()
  383. data["swap_mem"] = math.Round(swap.UsedPercent)
  384. vir, _ := mem.VirtualMemory()
  385. data["virtual_mem"] = math.Round(vir.UsedPercent)
  386. conn, _ := net.ProtoCounters(nil)
  387. io1, _ := net.IOCounters(false)
  388. time.Sleep(time.Millisecond * 500)
  389. io2, _ := net.IOCounters(false)
  390. if len(io2) > 0 && len(io1) > 0 {
  391. data["io_send"] = (io2[0].BytesSent - io1[0].BytesSent) * 2
  392. data["io_recv"] = (io2[0].BytesRecv - io1[0].BytesRecv) * 2
  393. }
  394. for _, v := range conn {
  395. data[v.Protocol] = v.Stats["CurrEstab"]
  396. }
  397. //chart
  398. var fg int
  399. if len(serverStatus) >= 10 {
  400. fg = len(serverStatus) / 10
  401. for i := 0; i <= 9; i++ {
  402. data["sys"+strconv.Itoa(i+1)] = serverStatus[i*fg]
  403. }
  404. }
  405. return data
  406. }
  407. func flowSession(m time.Duration) {
  408. ticker := time.NewTicker(m)
  409. for {
  410. select {
  411. case <-ticker.C:
  412. file.GetCsvDb().StoreHostToCsv()
  413. file.GetCsvDb().StoreTasksToCsv()
  414. }
  415. }
  416. }
  417. func getSeverStatus() {
  418. for {
  419. if len(serverStatus) < 10 {
  420. time.Sleep(time.Second)
  421. } else {
  422. time.Sleep(time.Minute)
  423. }
  424. cpuPercet, _ := cpu.Percent(0, true)
  425. var cpuAll float64
  426. for _, v := range cpuPercet {
  427. cpuAll += v
  428. }
  429. m := make(map[string]interface{})
  430. loads, _ := load.Avg()
  431. m["load1"] = loads.Load1
  432. m["load5"] = loads.Load5
  433. m["load15"] = loads.Load15
  434. m["cpu"] = math.Round(cpuAll / float64(len(cpuPercet)))
  435. swap, _ := mem.SwapMemory()
  436. m["swap_mem"] = math.Round(swap.UsedPercent)
  437. vir, _ := mem.VirtualMemory()
  438. m["virtual_mem"] = math.Round(vir.UsedPercent)
  439. conn, _ := net.ProtoCounters(nil)
  440. io1, _ := net.IOCounters(false)
  441. time.Sleep(time.Millisecond * 500)
  442. io2, _ := net.IOCounters(false)
  443. if len(io2) > 0 && len(io1) > 0 {
  444. m["io_send"] = (io2[0].BytesSent - io1[0].BytesSent) * 2
  445. m["io_recv"] = (io2[0].BytesRecv - io1[0].BytesRecv) * 2
  446. }
  447. t := time.Now()
  448. m["time"] = strconv.Itoa(t.Hour()) + ":" + strconv.Itoa(t.Minute()) + ":" + strconv.Itoa(t.Second())
  449. for _, v := range conn {
  450. m[v.Protocol] = v.Stats["CurrEstab"]
  451. }
  452. if len(serverStatus) >= 1440 {
  453. serverStatus = serverStatus[1:]
  454. }
  455. serverStatus = append(serverStatus, m)
  456. }
  457. }