From 5bead443ad23b279f2d6383a04ecb3fa6a116d27 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 7 Sep 2020 15:33:47 -0700 Subject: [PATCH] Handle port bindings correctly when using 127.0.0.1 closes pterodactyl/panel#2307 --- environment/allocations.go | 38 +++++++++++++++++++++++++++++++-- environment/docker/container.go | 2 +- server/server.go | 10 ++++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/environment/allocations.go b/environment/allocations.go index bf2d9c9..b48e294 100644 --- a/environment/allocations.go +++ b/environment/allocations.go @@ -3,6 +3,7 @@ package environment import ( "fmt" "github.com/docker/go-connections/nat" + "github.com/pterodactyl/wings/config" "strconv" ) @@ -25,6 +26,8 @@ type Allocations struct { // Converts the server allocation mappings into a format that can be understood by Docker. While // we do strive to support multiple environments, using Docker's standardized format for the // bindings certainly makes life a little easier for managing things. +// +// You'll want to use DockerBindings() if you need to re-map 127.0.0.1 to the Docker interface. func (a *Allocations) Bindings() nat.PortMap { var out = nat.PortMap{} @@ -50,16 +53,47 @@ func (a *Allocations) Bindings() nat.PortMap { return out } +// Returns the bindings for the server in a way that is supported correctly by Docker. This replaces +// any reference to 127.0.0.1 with the IP of the pterodactyl0 network interface which will allow the +// server to operate on a local address while still being accessible by other containers. +func (a *Allocations) DockerBindings() nat.PortMap { + iface := config.Get().Docker.Network.Interface + + out := a.Bindings() + // Loop over all of the bindings for this container, and convert any that reference 127.0.0.1 + // to use the pterodactyl0 network interface IP, as that is the true local for what people are + // trying to do when creating servers. + for p, binds := range out { + for i, alloc := range binds { + if alloc.HostIP != "127.0.0.1" { + continue + } + + // If using ISPN just delete the local allocation from the server. + if config.Get().Docker.Network.ISPN { + out[p] = append(out[p][:i], out[p][i+1:]...) + } else { + out[p][i] = nat.PortBinding{ + HostIP: iface, + HostPort: alloc.HostPort, + } + } + } + } + + return out +} + // Converts the server allocation mappings into a PortSet that can be understood // by Docker. This formatting is slightly different than "Bindings" as it should // return an empty struct rather than a binding. // -// To accomplish this, we'll just get the values from "Bindings" and then set them +// To accomplish this, we'll just get the values from "DockerBindings" and then set them // to empty structs. Because why not. func (a *Allocations) Exposed() nat.PortSet { var out = nat.PortSet{} - for port := range a.Bindings() { + for port := range a.DockerBindings() { out[port] = struct{}{} } diff --git a/environment/docker/container.go b/environment/docker/container.go index bb3bacb..9d2ffd9 100644 --- a/environment/docker/container.go +++ b/environment/docker/container.go @@ -164,7 +164,7 @@ func (e *Environment) Create() error { tmpfsSize := strconv.Itoa(int(config.Get().Docker.TmpfsSize)) hostConf := &container.HostConfig{ - PortBindings: a.Bindings(), + PortBindings: a.DockerBindings(), // Configure the mounts for this container. First mount the server data directory // into the container as a r/w bind. diff --git a/server/server.go b/server/server.go index 2f6996d..1fd64b2 100644 --- a/server/server.go +++ b/server/server.go @@ -6,6 +6,7 @@ import ( "github.com/apex/log" "github.com/pkg/errors" "github.com/pterodactyl/wings/api" + "github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment/docker" "github.com/pterodactyl/wings/events" @@ -74,11 +75,18 @@ func (s *Server) Id() string { func (s *Server) GetEnvironmentVariables() []string { zone, _ := time.Now().In(time.Local).Zone() + var ip = s.Config().Allocations.DefaultMapping.Ip + // Convert 127.0.0.1 to the pterodactyl0 network interface if the environment is Docker + // so that the server operates as expected. + if s.Environment.Type() == "docker" && ip == "127.0.0.1" { + ip = config.Get().Docker.Network.Interface + } + var out = []string{ fmt.Sprintf("TZ=%s", zone), fmt.Sprintf("STARTUP=%s", s.Config().Invocation), fmt.Sprintf("SERVER_MEMORY=%d", s.MemoryLimit()), - fmt.Sprintf("SERVER_IP=%s", s.Config().Allocations.DefaultMapping.Ip), + fmt.Sprintf("SERVER_IP=%s", ip), fmt.Sprintf("SERVER_PORT=%d", s.Config().Allocations.DefaultMapping.Port), }