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
3 changes: 3 additions & 0 deletions .github/contributors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,6 @@ users:
OdysseasKalaitsidis:
name: Odysseas Kalaitsidis
email: odysseaskalaitsides@gmail.com
alimx07:
name: Ali Mohamed
email: amx746@gmail.com
12 changes: 12 additions & 0 deletions .github/linters/urunc-dict.txt
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,15 @@ hyperlight
Hyperlight
Odysseas
Kalaitsidis
lhlog
dnat
PREROUTING
resolv
ndots
clsact
Sysctls
localnet
skbedit
ptype
pedit
nslookup
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/unikernels/*.go)
URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/types/*.go)
URUNC_SRC += $(wildcard $(CURDIR)/pkg/unikontainers/initrd/*.go)
URUNC_SRC += $(wildcard $(CURDIR)/pkg/network/*.go)
URUNC_SRC += $(wildcard $(CURDIR)/pkg/network/localhost/*.go)
SHIM_SRC := $(wildcard $(CURDIR)/cmd/containerd-shim-urunc-v2/*.go)
SHIM_SRC += $(wildcard $(CURDIR)/pkg/containerd-shim/*.go)
SHIM_SRC += $(wildcard $(CURDIR)/pkg/containerd-shim/containerd/*.go)
Expand Down Expand Up @@ -233,7 +234,7 @@ test: unittest e2etest

## unittest Run all unit tests
.PHONY: unittest
unittest: test_unikontainers test_metrics test_network test_hypervisors test_unikernels
unittest: test_unikontainers test_metrics test_network test_localhost test_hypervisors test_unikernels

## e2etest Run all end-to-end tests
.PHONY: e2etest
Expand All @@ -257,6 +258,12 @@ test_network:
@GOFLAGS=$(TEST_FLAGS) $(GO) test $(TEST_OPTS) ./pkg/network -v
@echo " "

## test_localhost Run unit tests for network/localhost package
test_localhost:
@echo "Unit testing in pkg/network/localhost"
@GOFLAGS=$(TEST_FLAGS) $(GO) test $(TEST_OPTS) ./pkg/network/localhost -v
@echo " "

## test_hypervisors Run unit tests for hypervisors package
test_hypervisors:
@echo "Unit testing in hypervisors"
Expand Down
5 changes: 3 additions & 2 deletions internal/constants/network_constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
StaticNetworkTapIP = "172.16.1.1"
StaticNetworkUnikernelIP = "172.16.1.2"
// TODO: Experiment with DynamicNetworkTapIP starting from 172.16.X.1
DynamicNetworkTapIP = "172.16.X.2"
QueueProxyRedirectIP = "172.16.1.2"
DynamicNetworkTapIP = "172.16.X.2"
QueueProxyRedirectIP = "172.16.1.2"
LocalhostDNSResolverIP = "192.168.100.100"
)
112 changes: 112 additions & 0 deletions pkg/network/localhost/docker.go
Comment thread
alimx07 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright (c) 2023-2026, Nubificus LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package localhost

import (
"errors"
"fmt"
"net"
"os/exec"
"strings"
"syscall"

"github.com/vishvananda/netlink"
)

func dockerRules(f *Forwarder) error {

tcpPort, udpPort, err := dockerDNSPorts(f.LoIP)
if err != nil {
return err
}
lhlog.Debugf("Docker DNS resolver: tcp/%s udp/%s", tcpPort, udpPort)

if err := dnat(f.VirtIP, "udp", net.JoinHostPort(f.LoIP.String(), udpPort)); err != nil {
return err
}
if err := dnat(f.VirtIP, "tcp", net.JoinHostPort(f.LoIP.String(), tcpPort)); err != nil {
return err
}
lhlog.Debug("Applied Docker DNAT rules")

return nil
}

func dockerDNSPorts(loIP net.IP) (string, string, error) {
var tcpPort, udpPort string

// syscall.AF_INET : IPv4
tcp, err := netlink.SocketDiagTCPInfo(syscall.AF_INET)
if err != nil {
return "", "", fmt.Errorf("could not list TCP sockets in namespace: %w", err)
}
for _, s := range tcp {
if s.InetDiagMsg.ID.Source.String() == loIP.String() && s.InetDiagMsg.ID.Destination.String() == "0.0.0.0" && int(s.InetDiagMsg.State) == netlink.TCP_LISTEN {
tcpPort = fmt.Sprintf("%d", s.InetDiagMsg.ID.SourcePort)
break
}
}
udp, err := netlink.SocketDiagUDPInfo(syscall.AF_INET)
if err != nil {
return "", "", fmt.Errorf("could not list UDP sockets in namespace: %w", err)
}
for _, s := range udp {

// As udp has no connection states as tcp. by default (which is our case) it should have tcp_close (7) state to read it as "no peer association"
// TODO: is there any other states that could make this condition fails ?
if s.InetDiagMsg.ID.Source.String() == loIP.String() && s.InetDiagMsg.ID.Destination.String() == "0.0.0.0" && int(s.InetDiagMsg.State) == netlink.TCP_CLOSE {
udpPort = fmt.Sprintf("%d", s.InetDiagMsg.ID.SourcePort)
break
}
}
if tcpPort == "" || udpPort == "" {
return "", "", fmt.Errorf("could not find docker embedded resolver ports for %s (tcp=%q udp=%q)", loIP, tcpPort, udpPort)
}
return tcpPort, udpPort, nil
}

Comment thread
cmainas marked this conversation as resolved.
// ClearRules removes DNAT rules dockerRules could have added.
func clearRules() error {

// This will be run from kill() so no memory state could be used.
Comment thread
cmainas marked this conversation as resolved.
// we list all IPtable rules from scratch.

// iptables-save output example:
// -A PREROUTING -d 192.168.100.100/32 -i lo -p udp -j DNAT --to-destination 127.0.0.11:60269
ipt, err := exec.LookPath("iptables-save")
if err != nil {
return err
}
out, err := exec.Command(ipt, "-t", "nat").Output() //nolint:gosec
if err != nil {
return fmt.Errorf("iptables-save failed: %w", err)
}

var retErr error
for line := range strings.SplitSeq(string(out), "\n") {
fields := strings.Fields(line)
if len(fields) < 2 || fields[0] != "-A" || fields[1] != "PREROUTING" {
continue
}
if !strings.Contains(line, "-i lo") || !strings.Contains(line, "-j DNAT") {
continue
}
args := append([]string{"-t", "nat", "-D"}, fields[1:]...)
if err := ipTablesExec(args); err != nil {
retErr = errors.Join(retErr, err)
}
}
return retErr
}
Loading
Loading