main.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package main
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "flag"
  6. "fmt"
  7. "log"
  8. "net/http"
  9. "os"
  10. "os/signal"
  11. "sync"
  12. "syscall"
  13. "time"
  14. "proxmox-router/internal/api"
  15. "proxmox-router/internal/auth"
  16. "proxmox-router/internal/bridge"
  17. "proxmox-router/internal/bwtest"
  18. "proxmox-router/internal/certs"
  19. "proxmox-router/internal/cli"
  20. "proxmox-router/internal/dhcp"
  21. "proxmox-router/internal/dns"
  22. "proxmox-router/internal/dynamicrouting"
  23. "proxmox-router/internal/firewall"
  24. "proxmox-router/internal/logging"
  25. "proxmox-router/internal/network"
  26. "proxmox-router/internal/routing"
  27. "proxmox-router/internal/services"
  28. "proxmox-router/internal/tools"
  29. "proxmox-router/internal/vpn"
  30. "proxmox-router/internal/vrrp"
  31. "proxmox-router/internal/web"
  32. )
  33. func main() {
  34. addr := flag.String("addr", ":8080", "HTTP service address (e.g. :8080 or :80)")
  35. cliAddr := flag.String("cli-addr", ":8282", "CLI service address for Telnet and debtik-cli (e.g. :8282)")
  36. metaPath := flag.String("meta", "/etc/proxmox-router/metadata.json", "Path to interface metadata storage file")
  37. flag.Parse()
  38. // Initialize Logging Ring Buffer
  39. _ = logging.GetLogger()
  40. // Initialize components
  41. metaMgr := network.NewMetadataManager(*metaPath)
  42. netMgr := network.NewManager(metaMgr)
  43. persistMgr := network.NewPersistenceManager(netMgr)
  44. vpnMgr := vpn.NewManager()
  45. defer vpnMgr.AeroTUN.StopAll()
  46. fwMgr := firewall.NewFirewallManager()
  47. routingMgr := routing.NewRoutingManager()
  48. defer routingMgr.Stop()
  49. dynRoutingMgr := dynamicrouting.NewManager("")
  50. bridgeMgr := bridge.NewBridgeManager()
  51. toolsMgr := tools.NewManager()
  52. dhcpMgr := dhcp.NewManager()
  53. dhcpServerMgr := dhcp.NewServerManager()
  54. vrrpMgr := vrrp.NewManager()
  55. bwtestMgr := bwtest.NewManager("")
  56. defer bwtestMgr.Stop()
  57. dnsMgr := dns.NewManager()
  58. authMgr := auth.NewManager("")
  59. servicesMgr := services.NewManager("")
  60. certMgr, err := certs.NewCertManager("")
  61. if err != nil {
  62. log.Fatalf("Failed to initialize certificate manager: %v", err)
  63. }
  64. webHandler := web.Handler()
  65. // Build Unified RouterOS CLI Executor
  66. cliExecutor := cli.NewExecutor(
  67. authMgr,
  68. netMgr,
  69. routingMgr,
  70. dynRoutingMgr,
  71. fwMgr,
  72. dhcpMgr,
  73. dhcpServerMgr,
  74. dnsMgr,
  75. bridgeMgr,
  76. vpnMgr,
  77. vrrpMgr,
  78. bwtestMgr,
  79. servicesMgr,
  80. certMgr,
  81. )
  82. // Determine Telnet & SSH addresses from services config or flags
  83. telnetAddr := *cliAddr
  84. if tSvc, ok := servicesMgr.GetService("telnet"); ok && tSvc.Port > 0 {
  85. telnetAddr = fmt.Sprintf(":%d", tSvc.Port)
  86. }
  87. sshAddr := ":2222"
  88. if sSvc, ok := servicesMgr.GetService("ssh"); ok && sSvc.Port > 0 {
  89. sshAddr = fmt.Sprintf(":%d", sSvc.Port)
  90. }
  91. cliTelnetServer := cli.NewServer(telnetAddr, authMgr, cliExecutor)
  92. cliSSHServer := cli.NewSSHServer(sshAddr, authMgr, cliExecutor)
  93. // Register hooks for dynamic service start/stop & port changes
  94. servicesMgr.RegisterHook("telnet", func(serviceName string, port int, disabled bool) error {
  95. cliTelnetServer.Stop()
  96. if !disabled {
  97. cliTelnetServer.SetAddr(fmt.Sprintf(":%d", port))
  98. go func() {
  99. if err := cliTelnetServer.Start(); err != nil {
  100. log.Printf("[CLI-Telnet] Listener error: %v", err)
  101. }
  102. }()
  103. }
  104. return nil
  105. })
  106. servicesMgr.RegisterHook("ssh", func(serviceName string, port int, disabled bool) error {
  107. cliSSHServer.Stop()
  108. if !disabled {
  109. cliSSHServer.SetAddr(fmt.Sprintf(":%d", port))
  110. go func() {
  111. if err := cliSSHServer.Start(); err != nil {
  112. log.Printf("[CLI-SSH] Listener error: %v", err)
  113. }
  114. }()
  115. }
  116. return nil
  117. })
  118. // Start enabled CLI servers
  119. if tSvc, ok := servicesMgr.GetService("telnet"); !ok || !tSvc.Disabled {
  120. go func() {
  121. if err := cliTelnetServer.Start(); err != nil {
  122. log.Printf("[CLI-Telnet] Server listener error: %v", err)
  123. }
  124. }()
  125. }
  126. defer cliTelnetServer.Stop()
  127. if sSvc, ok := servicesMgr.GetService("ssh"); !ok || !sSvc.Disabled {
  128. go func() {
  129. if err := cliSSHServer.Start(); err != nil {
  130. log.Printf("[CLI-SSH] Server listener error: %v", err)
  131. }
  132. }()
  133. }
  134. defer cliSSHServer.Stop()
  135. // API & Web UI Server
  136. srv := api.NewServer(
  137. netMgr,
  138. persistMgr,
  139. metaMgr,
  140. vpnMgr,
  141. fwMgr,
  142. routingMgr,
  143. dynRoutingMgr,
  144. bridgeMgr,
  145. toolsMgr,
  146. dhcpMgr,
  147. dhcpServerMgr,
  148. vrrpMgr,
  149. bwtestMgr,
  150. dnsMgr,
  151. authMgr,
  152. servicesMgr,
  153. certMgr,
  154. webHandler,
  155. )
  156. // HTTPS (www-ssl) Dynamic Server Listener
  157. var (
  158. httpsServer *http.Server
  159. httpsMu sync.Mutex
  160. httpsRunning bool
  161. )
  162. startOrRestartHTTPS := func(port int, disabled bool) {
  163. httpsMu.Lock()
  164. defer httpsMu.Unlock()
  165. if httpsRunning && httpsServer != nil {
  166. ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
  167. _ = httpsServer.Shutdown(ctx)
  168. cancel()
  169. httpsRunning = false
  170. httpsServer = nil
  171. }
  172. if disabled {
  173. log.Printf("[HTTPS] Web SSL (www-ssl) listener stopped")
  174. return
  175. }
  176. sslSvc, ok := servicesMgr.GetService("www-ssl")
  177. if !ok || sslSvc.Certificate == "" {
  178. log.Printf("[HTTPS] Cannot start www-ssl: no certificate configured (set certificate=<name>)")
  179. return
  180. }
  181. tlsCert, err := certMgr.GetTLSCertificate(sslSvc.Certificate)
  182. if err != nil {
  183. log.Printf("[HTTPS] Cannot start www-ssl: failed loading certificate %q: %v", sslSvc.Certificate, err)
  184. return
  185. }
  186. tlsConfig := &tls.Config{
  187. Certificates: []tls.Certificate{tlsCert},
  188. GetCertificate: func(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
  189. curSvc, ok := servicesMgr.GetService("www-ssl")
  190. if ok && curSvc.Certificate != "" {
  191. if c, err := certMgr.GetTLSCertificate(curSvc.Certificate); err == nil {
  192. return &c, nil
  193. }
  194. }
  195. return &tlsCert, nil
  196. },
  197. }
  198. listenAddr := fmt.Sprintf(":%d", port)
  199. newSrv := &http.Server{
  200. Addr: listenAddr,
  201. Handler: srv,
  202. TLSConfig: tlsConfig,
  203. ReadTimeout: 60 * time.Second,
  204. WriteTimeout: 60 * time.Second,
  205. IdleTimeout: 120 * time.Second,
  206. }
  207. httpsServer = newSrv
  208. httpsRunning = true
  209. go func() {
  210. log.Printf("[HTTPS] Web SSL (www-ssl) server listening on %s with certificate %q", listenAddr, sslSvc.Certificate)
  211. if err := newSrv.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed {
  212. log.Printf("[HTTPS] Server error: %v", err)
  213. httpsMu.Lock()
  214. httpsRunning = false
  215. httpsMu.Unlock()
  216. }
  217. }()
  218. }
  219. servicesMgr.RegisterHook("www-ssl", func(serviceName string, port int, disabled bool) error {
  220. startOrRestartHTTPS(port, disabled)
  221. return nil
  222. })
  223. if sslSvc, ok := servicesMgr.GetService("www-ssl"); ok && !sslSvc.Disabled {
  224. startOrRestartHTTPS(sslSvc.Port, sslSvc.Disabled)
  225. }
  226. defer func() {
  227. httpsMu.Lock()
  228. if httpsRunning && httpsServer != nil {
  229. _ = httpsServer.Close()
  230. }
  231. httpsMu.Unlock()
  232. }()
  233. httpServer := &http.Server{
  234. Addr: *addr,
  235. Handler: srv,
  236. ReadTimeout: 60 * time.Second,
  237. WriteTimeout: 60 * time.Second,
  238. IdleTimeout: 120 * time.Second,
  239. }
  240. // Print startup banner
  241. fmt.Println("========================================================")
  242. fmt.Println(" ⚡ DebTik Appliance Controller ⚡ ")
  243. fmt.Println("========================================================")
  244. fmt.Printf(" Web UI & API : http://0.0.0.0%s\n", *addr)
  245. fmt.Printf(" CLI Telnet Service : 0.0.0.0%s (debtik-cli / telnet)\n", telnetAddr)
  246. fmt.Printf(" CLI SSH Service : 0.0.0.0%s (ssh admin@<router-ip> -p 2222)\n", sshAddr)
  247. fmt.Printf(" Metadata Storage : %s\n", *metaPath)
  248. fmt.Printf(" Debian Config Path : %s\n", network.DebianVlansCfgPath)
  249. if ifaces, err := netMgr.ListInterfaces(); err == nil {
  250. fmt.Printf(" Discovered Links : %d interfaces\n", len(ifaces))
  251. for _, i := range ifaces {
  252. fmt.Printf(" - %-10s (%s) [%s] MTU:%d\n", i.Name, i.Type, i.State, i.MTU)
  253. }
  254. }
  255. fmt.Println("========================================================")
  256. fmt.Println(" DebTik Appliance ready. Press Ctrl+C to terminate.")
  257. // Graceful shutdown handling
  258. stopChan := make(chan os.Signal, 1)
  259. signal.Notify(stopChan, os.Interrupt, syscall.SIGTERM)
  260. go func() {
  261. if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
  262. log.Fatalf("HTTP server failed: %v", err)
  263. }
  264. }()
  265. <-stopChan
  266. fmt.Println("\nShutting down DebTik Controller gracefully...")
  267. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  268. defer cancel()
  269. if err := httpServer.Shutdown(ctx); err != nil {
  270. log.Printf("Server shutdown error: %v", err)
  271. }
  272. fmt.Println("DebTik Controller stopped.")
  273. }