Add service proxy

This adds a service proxy based on nfproxy and changes to the service IP allocation to make it work.
Also adds support for masquerading outbound traffic for outbound network connectivity.

Test Plan:
Currently manually tested by creating an alpine pod and running 'apk add curl && curl -k https://192.168.188.1:443/'.
Will be covered later by CTS.

Bug: T810

X-Origin-Diff: phab/D580
GitOrigin-RevId: cace863fd8c2f045560f8abf84c40cc77bc275d4
diff --git a/core/internal/network/main.go b/core/internal/network/main.go
index ac9ce46..c92b21a 100644
--- a/core/internal/network/main.go
+++ b/core/internal/network/main.go
@@ -23,6 +23,9 @@
 	"net"
 	"os"
 
+	"github.com/google/nftables"
+	"github.com/google/nftables/expr"
+
 	"github.com/vishvananda/netlink"
 	"go.uber.org/zap"
 	"golang.org/x/sys/unix"
@@ -97,6 +100,13 @@
 	return nil
 }
 
+// nfifname converts an interface name into 16 bytes padded with zeroes (for nftables)
+func nfifname(n string) []byte {
+	b := make([]byte, 16)
+	copy(b, []byte(n+"\x00"))
+	return b
+}
+
 func (s *Service) useInterface(ctx context.Context, iface netlink.Link) error {
 	err := supervisor.Run(ctx, "dhcp", s.dhcp.Run(iface))
 	if err != nil {
@@ -115,6 +125,40 @@
 		s.logger.Warn("failed to add routes", zap.Error(err))
 	}
 
+	c := nftables.Conn{}
+
+	nat := c.AddTable(&nftables.Table{
+		Family: nftables.TableFamilyIPv4,
+		Name:   "nat",
+	})
+
+	postrouting := c.AddChain(&nftables.Chain{
+		Name:     "postrouting",
+		Hooknum:  nftables.ChainHookPostrouting,
+		Priority: nftables.ChainPriorityNATSource,
+		Table:    nat,
+		Type:     nftables.ChainTypeNAT,
+	})
+
+	// Masquerade/SNAT all traffic going out of the external interface
+	c.AddRule(&nftables.Rule{
+		Table: nat,
+		Chain: postrouting,
+		Exprs: []expr.Any{
+			&expr.Meta{Key: expr.MetaKeyOIFNAME, Register: 1},
+			&expr.Cmp{
+				Op:       expr.CmpOpEq,
+				Register: 1,
+				Data:     nfifname(iface.Attrs().Name),
+			},
+			&expr.Masq{},
+		},
+	})
+
+	if err := c.Flush(); err != nil {
+		panic(err)
+	}
+
 	return nil
 }