Add auth-managed proxy UI improvements

This commit is contained in:
2026-04-03 20:58:54 -04:00
parent 7ed709ad3d
commit f2a246ce6b
9 changed files with 1384 additions and 82 deletions

View File

@ -28,19 +28,34 @@ func Run(cfg Config) error {
db := noodle.NewDatabase(cfg.DataPath)
defer db.Close()
auth, err := web.NewAuth(db)
if err != nil {
return err
}
if err := auth.EnsureDefaultUser(); err != nil {
return err
}
if cfg.RunTest {
runTestSequence(db)
}
go systemCheck(db, noodleChannel)
go expirationCheck(db, noodleChannel)
go proxify(noodleChannel)
go proxify(db, noodleChannel)
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(web.StaticFiles()))))
http.HandleFunc("/", web.HandleMain(db, &noodleChannel))
http.HandleFunc("/add", web.HandleAdd(db, &noodleChannel))
http.HandleFunc("/toggle", web.HandleToggle(db, &noodleChannel))
http.HandleFunc("/delete", web.HandleDelete(db, &noodleChannel))
http.HandleFunc("/login", auth.HandleLogin())
http.HandleFunc("/logout", auth.HandleLogout())
http.HandleFunc("/", auth.RequireAuth(web.HandleMain(db, &noodleChannel, auth)))
http.HandleFunc("/users", auth.RequireAuth(web.HandleUsers(auth, db)))
http.HandleFunc("/users/add", auth.RequireAdmin(web.HandleAddUser(auth, db)))
http.HandleFunc("/users/role", auth.RequireAdmin(web.HandleSetUserRole(auth, db)))
http.HandleFunc("/users/password", auth.RequireAuth(web.HandleChangePassword(auth, db)))
http.HandleFunc("/users/delete", auth.RequireAuth(web.HandleDeleteUser(auth, db)))
http.HandleFunc("/add", auth.RequireAuth(web.HandleAdd(db, &noodleChannel, auth)))
http.HandleFunc("/toggle", auth.RequireAuth(web.HandleToggle(db, &noodleChannel)))
http.HandleFunc("/delete", auth.RequireAuth(web.HandleDelete(db, &noodleChannel)))
log.Printf("Server starting on %s", listenAddr)
return http.ListenAndServe(listenAddr, nil)
@ -56,7 +71,7 @@ func systemCheck(db *noodle.Database, noodleChannel chan noodle.Noodle) {
}
}
func proxify(noodleChannel chan noodle.Noodle) {
func proxify(db *noodle.Database, noodleChannel chan noodle.Noodle) {
noodleMap := make(map[string]managedProxy)
for {
item := <-noodleChannel
@ -65,6 +80,9 @@ func proxify(noodleChannel chan noodle.Noodle) {
proxy, err := newProxy(item)
if err != nil {
log.Print(err)
if _, updateErr := db.SetIsUp(item.Id, false); updateErr != nil {
log.Print(updateErr)
}
continue
}
noodleMap[item.Id] = proxy
@ -408,15 +426,73 @@ func (p *udpNoodleProxy) Close() error {
return conn.Close()
}
func allowSource(allowedIP string, addr net.Addr) bool {
if allowedIP == "" || allowedIP == "All" {
func allowSource(allowedIPs string, addr net.Addr) bool {
if allowedIPs == "" || strings.EqualFold(strings.TrimSpace(allowedIPs), "All") {
return true
}
host, _, err := net.SplitHostPort(addr.String())
if err != nil {
return false
}
return host == allowedIP
hostIP := normalizeIP(net.ParseIP(host))
if hostIP == nil {
return false
}
for _, item := range strings.Split(allowedIPs, ",") {
entry := strings.TrimSpace(item)
if strings.Contains(entry, "/") {
_, network, err := net.ParseCIDR(entry)
if err == nil && networkContainsIP(network, hostIP) {
return true
}
continue
}
entryIP := normalizeIP(net.ParseIP(entry))
if entryIP != nil && entryIP.Equal(hostIP) {
return true
}
}
return false
}
func normalizeIP(ip net.IP) net.IP {
if ip == nil {
return nil
}
if v4 := ip.To4(); v4 != nil {
return v4
}
return ip
}
func networkContainsIP(network *net.IPNet, ip net.IP) bool {
if network == nil || ip == nil {
return false
}
if network.Contains(ip) {
return true
}
networkIP := normalizeIP(network.IP)
normalizedIP := normalizeIP(ip)
if networkIP == nil || normalizedIP == nil {
return false
}
if len(networkIP) != len(normalizedIP) {
return false
}
mask := network.Mask
if len(mask) != len(normalizedIP) {
return false
}
for i := range normalizedIP {
if normalizedIP[i]&mask[i] != networkIP[i]&mask[i] {
return false
}
}
return true
}
func closeWrite(conn net.Conn) {
@ -440,42 +516,9 @@ func expirationCheck(db *noodle.Database, noodleChannel chan noodle.Noodle) {
defer ticker.Stop()
for range ticker.C {
noodles := db.GetAll()
for _, item := range noodles {
if !item.IsUp {
continue
}
if item.Expiration <= 0 {
if item.IsUp {
item.IsUp = false
noodleChannel <- item
}
if err := db.Delete(item.Id); err != nil {
log.Print(err)
}
continue
}
item.Expiration -= time.Second
if item.Expiration <= 0 {
item.Expiration = 0
if err := db.Update(item); err != nil {
log.Print(err)
continue
}
if item.IsUp {
item.IsUp = false
noodleChannel <- item
}
if err := db.Delete(item.Id); err != nil {
log.Print(err)
}
continue
}
if err := db.Update(item); err != nil {
log.Print(err)
}
stopped := db.TickExpirations()
for _, item := range stopped {
noodleChannel <- item
}
}
}