🏡 index : quine-global/quintodrome.git

package netguard_test

import (
	"net"
	"net/netip"

	"github.com/navidrome/navidrome/utils/netguard"
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

var _ = Describe("netguard", func() {
	DescribeTable("IsPrivateIP",
		func(addr string, expected bool) {
			Expect(netguard.IsPrivateIP(net.ParseIP(addr))).To(Equal(expected))
		},
		Entry("IPv4 loopback", "127.0.0.1", true),
		Entry("IPv4 loopback range", "127.0.0.2", true),
		Entry("IPv6 loopback", "::1", true),
		Entry("IPv4-mapped IPv6 loopback", "::ffff:127.0.0.1", true),
		Entry("10.x", "10.1.2.3", true),
		Entry("172.16.x", "172.16.0.1", true),
		Entry("192.168.x", "192.168.1.10", true),
		Entry("IPv6 unique local", "fd00::1", true),
		Entry("link-local (cloud metadata)", "169.254.169.254", true),
		Entry("IPv6 link-local", "fe80::1", true),
		Entry("link-local multicast", "224.0.0.1", true),
		Entry("IPv4 unspecified", "0.0.0.0", true),
		Entry("IPv6 unspecified", "::", true),
		Entry("public IPv4", "93.184.216.34", false),
		Entry("172.32.x is outside the private block", "172.32.0.1", false),
		Entry("public IPv6", "2606:4700:4700::1111", false),
	)

	Describe("DialControl", func() {
		It("rejects private and loopback addresses", func() {
			control := netguard.DialControl()
			for _, addr := range []string{"127.0.0.1:80", "[::1]:443", "169.254.169.254:80", "10.0.0.1:8080", "0.0.0.0:80"} {
				Expect(control("tcp", addr, nil)).To(MatchError(netguard.ErrPrivateAddress), addr)
			}
		})

		It("allows public addresses", func() {
			control := netguard.DialControl()
			Expect(control("tcp", "93.184.216.34:443", nil)).To(Succeed())
			Expect(control("tcp6", "[2606:4700:4700::1111]:443", nil)).To(Succeed())
		})

		It("allows private addresses covered by an allowed prefix, and only those", func() {
			control := netguard.DialControl(netip.MustParsePrefix("127.0.0.1/32"))
			Expect(control("tcp", "127.0.0.1:8080", nil)).To(Succeed())
			Expect(control("tcp", "127.0.0.2:8080", nil)).To(MatchError(netguard.ErrPrivateAddress))
		})

		It("matches IPv4-mapped IPv6 addresses against IPv4 prefixes", func() {
			control := netguard.DialControl(netip.MustParsePrefix("127.0.0.0/8"))
			Expect(control("tcp", "[::ffff:127.0.0.1]:80", nil)).To(Succeed())
		})

		It("fails closed when the address is not an IP", func() {
			Expect(netguard.DialControl()("tcp", "localhost:80", nil)).To(HaveOccurred())
			Expect(netguard.DialControl()("tcp", "garbage", nil)).To(HaveOccurred())
		})
	})
})