Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions environment/allocations.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,26 +65,36 @@ func (a *Allocations) Bindings() nat.PortMap {
// 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
nw := config.Get().Docker.Network

out := a.Bindings()
// Loop over all 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 {
if nw.ISPN {
filtered := binds[:0]
for _, alloc := range binds {
if alloc.HostIP != "127.0.0.1" {
filtered = append(filtered, alloc)
}
}
if len(filtered) == 0 {
delete(out, p)
} else {
out[p] = filtered
}
continue
}

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,
}
out[p][i] = nat.PortBinding{
HostIP: nw.Interface,
HostPort: alloc.HostPort,
}
}
}
Expand Down
65 changes: 65 additions & 0 deletions environment/allocations_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package environment

import (
"testing"

"github.com/docker/go-connections/nat"

"github.com/pterodactyl/wings/config"
)

func configureNetwork(t *testing.T, ispn bool) {
t.Helper()

cfg, err := config.NewAtPath("")
if err != nil {
t.Fatal(err)
}
cfg.Docker.Network.Interface = "172.18.0.1"
cfg.Docker.Network.ISPN = ispn
config.Set(cfg)
}

func TestAllocationsDockerBindingsRewritesLocalhostBindings(t *testing.T) {
configureNetwork(t, false)

allocations := Allocations{
Mappings: map[string][]int{
"127.0.0.1": {25565, 25565},
},
}

bindings := allocations.DockerBindings()
for _, port := range []nat.Port{"25565/tcp", "25565/udp"} {
got := bindings[port]
if len(got) != 2 {
t.Fatalf("expected two bindings for %s, got %d", port, len(got))
}
for _, binding := range got {
if binding.HostIP != "172.18.0.1" {
t.Fatalf("expected binding for %s to use interface IP, got %q", port, binding.HostIP)
}
}
}
}

func TestAllocationsDockerBindingsDropsLocalhostBindingsForISPN(t *testing.T) {
configureNetwork(t, true)

allocations := Allocations{
Mappings: map[string][]int{
"127.0.0.1": {25565, 25565},
},
}

bindings := allocations.DockerBindings()
for _, port := range []nat.Port{"25565/tcp", "25565/udp"} {
if got, ok := bindings[port]; ok {
t.Fatalf("expected no bindings for %s, got %d", port, len(got))
}
}

if exposed := allocations.Exposed(); len(exposed) != 0 {
t.Fatalf("expected no exposed ports, got %d", len(exposed))
}
}