smarter port selection

This commit is contained in:
yusing 2024-03-29 13:55:28 +00:00
parent 73dfc17a82
commit c445d50221
4 changed files with 48 additions and 16 deletions

Binary file not shown.

View file

@ -12,7 +12,7 @@ import (
) )
var ( var (
ImageNamePortMap = map[string]string{ ImageNamePortMapTCP = map[string]string{
"postgres": "5432", "postgres": "5432",
"mysql": "3306", "mysql": "3306",
"mariadb": "3306", "mariadb": "3306",
@ -22,7 +22,7 @@ var (
"rabbitmq": "5672", "rabbitmq": "5672",
"mongo": "27017", "mongo": "27017",
} }
ExtraNamePortMap = map[string]string{ ExtraNamePortMapTCP = map[string]string{
"dns": "53", "dns": "53",
"ssh": "22", "ssh": "22",
"ftp": "21", "ftp": "21",
@ -30,24 +30,42 @@ var (
"pop3": "110", "pop3": "110",
"imap": "143", "imap": "143",
} }
NamePortMap = func() map[string]string { NamePortMapTCP = func() map[string]string {
m := make(map[string]string) m := make(map[string]string)
for k, v := range ImageNamePortMap { for k, v := range ImageNamePortMapTCP {
m[k] = v m[k] = v
} }
for k, v := range ExtraNamePortMap { for k, v := range ExtraNamePortMapTCP {
m[k] = v m[k] = v
} }
return m return m
}() }()
) )
var ImageNamePortMapHTTP = map[string]uint16{
"nginx": 80,
"httpd": 80,
"adguardhome": 3000,
"gogs": 3000,
"gitea": 3000,
"portainer": 9000,
"portainer-ce": 9000,
"home-assistant": 8123,
"homebridge": 8581,
"uptime-kuma": 3001,
"changedetection.io": 3000,
"prometheus": 9090,
"grafana": 3000,
"dockge": 5001,
"nginx-proxy-manager": 81,
}
var wellKnownHTTPPorts = map[uint16]bool{ var wellKnownHTTPPorts = map[uint16]bool{
80: true, 80: true,
8000: true, 8000: true,
8008: true, // alternative HTTP port 8008: true,
8080: true, 8080: true,
3000: true, // adguardhome, gogs, etc 3000: true,
} }
var ( var (

View file

@ -23,7 +23,7 @@ func (p *Provider) setConfigField(c *ProxyConfig, label string, value string, pr
return nil return nil
} }
func (p *Provider) getContainerProxyConfigs(container types.Container, clientIP string) ProxyConfigSlice { func (p *Provider) getContainerProxyConfigs(container *types.Container, clientIP string) ProxyConfigSlice {
var aliases []string var aliases []string
cfgs := make(ProxyConfigSlice, 0) cfgs := make(ProxyConfigSlice, 0)
@ -61,7 +61,7 @@ func (p *Provider) getContainerProxyConfigs(container types.Container, clientIP
} }
} }
if config.Port == "" { if config.Port == "" {
config.Port = fmt.Sprintf("%d", selectPort(&container)) config.Port = fmt.Sprintf("%d", selectPort(container))
} }
if config.Port == "0" { if config.Port == "0" {
l.Infof("no ports exposed, ignored") l.Infof("no ports exposed, ignored")
@ -74,10 +74,8 @@ func (p *Provider) getContainerProxyConfigs(container types.Container, clientIP
case strings.HasPrefix(container.Image, "sha256:"): case strings.HasPrefix(container.Image, "sha256:"):
config.Scheme = "http" config.Scheme = "http"
default: default:
imageSplit := strings.Split(container.Image, "/") imageName := getImageName(container)
imageSplit = strings.Split(imageSplit[len(imageSplit)-1], ":") _, isKnownImage := ImageNamePortMapTCP[imageName]
imageName := imageSplit[0]
_, isKnownImage := ImageNamePortMap[imageName]
if isKnownImage { if isKnownImage {
config.Scheme = "tcp" config.Scheme = "tcp"
} else { } else {
@ -182,13 +180,18 @@ func (p *Provider) getDockerProxyConfigs() (ProxyConfigSlice, error) {
cfgs := make(ProxyConfigSlice, 0) cfgs := make(ProxyConfigSlice, 0)
for _, container := range containerSlice { for _, container := range containerSlice {
cfgs = append(cfgs, p.getContainerProxyConfigs(container, clientIP)...) cfgs = append(cfgs, p.getContainerProxyConfigs(&container, clientIP)...)
} }
return cfgs, nil return cfgs, nil
} }
// var dockerUrlRegex = regexp.MustCompile(`^(?P<scheme>\w+)://(?P<host>[^:]+)(?P<port>:\d+)?(?P<path>/.*)?$`) // var dockerUrlRegex = regexp.MustCompile(`^(?P<scheme>\w+)://(?P<host>[^:]+)(?P<port>:\d+)?(?P<path>/.*)?$`)
func getImageName(c *types.Container) string {
imageSplit := strings.Split(c.Image, "/")
imageSplit = strings.Split(imageSplit[len(imageSplit)-1], ":")
return imageSplit[0]
}
func getPublicPort(p types.Port) uint16 { return p.PublicPort } func getPublicPort(p types.Port) uint16 { return p.PublicPort }
func getPrivatePort(p types.Port) uint16 { return p.PrivatePort } func getPrivatePort(p types.Port) uint16 { return p.PrivatePort }
@ -201,11 +204,22 @@ func selectPort(c *types.Container) uint16 {
} }
func selectPortInternal(c *types.Container, getPort func(types.Port) uint16) uint16 { func selectPortInternal(c *types.Container, getPort func(types.Port) uint16) uint16 {
imageName := getImageName(c)
// if is known image -> use known port
if port, isKnown := ImageNamePortMapHTTP[imageName]; isKnown {
for _, p := range c.Ports {
if p.PrivatePort == port {
return getPort(p)
}
}
}
// if it has known http port -> use it
for _, p := range c.Ports { for _, p := range c.Ports {
if isWellKnownHTTPPort(p.PrivatePort) { if isWellKnownHTTPPort(p.PrivatePort) {
return getPort(p) return getPort(p)
} }
} }
// if it has any port -> use it
for _, p := range c.Ports { for _, p := range c.Ports {
if port := getPort(p); port != 0 { if port := getPort(p); port != 0 {
return port return port
@ -217,4 +231,4 @@ func selectPortInternal(c *types.Container, getPort func(types.Port) uint16) uin
func isWellKnownHTTPPort(port uint16) bool { func isWellKnownHTTPPort(port uint16) bool {
_, ok := wellKnownHTTPPorts[port] _, ok := wellKnownHTTPPorts[port]
return ok return ok
} }

View file

@ -58,7 +58,7 @@ func newStreamRouteBase(config *ProxyConfig) (*StreamRouteBase, error) {
dstPort = portSplit[1] dstPort = portSplit[1]
} }
if port, hasName := NamePortMap[dstPort]; hasName { if port, hasName := NamePortMapTCP[dstPort]; hasName {
dstPort = port dstPort = port
} }