mirror of
https://github.com/containers/podman.git
synced 2025-09-25 07:44:24 +08:00
@ -562,9 +562,14 @@ Valid values are:
|
|||||||
- `ns:<path>`: path to a network namespace to join
|
- `ns:<path>`: path to a network namespace to join
|
||||||
- `private`: create a new namespace for the container (default)
|
- `private`: create a new namespace for the container (default)
|
||||||
- `slirp4netns[:OPTIONS,...]`: use slirp4netns to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
|
- `slirp4netns[:OPTIONS,...]`: use slirp4netns to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
|
||||||
**port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default.
|
- **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default is false.
|
||||||
**port_handler=slirp4netns**: Use the slirp4netns port forwarding.
|
- **enable_ipv6=true|false**: Enable IPv6. Default is false. (Required for `outbound_addr6`).
|
||||||
**allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default to false.
|
- **outbound_addr=INTERFACE**: Specify the outbound interface slirp should bind to (ipv4 traffic only).
|
||||||
|
- **outbound_addr=IPv4**: Specify the outbound ipv4 address slirp should bind to.
|
||||||
|
- **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only).
|
||||||
|
- **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to.
|
||||||
|
- **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default.
|
||||||
|
- **port_handler=slirp4netns**: Use the slirp4netns port forwarding.
|
||||||
|
|
||||||
**--network-alias**=*alias*
|
**--network-alias**=*alias*
|
||||||
|
|
||||||
|
@ -171,6 +171,8 @@ type slirpFeatures struct {
|
|||||||
HasMTU bool
|
HasMTU bool
|
||||||
HasEnableSandbox bool
|
HasEnableSandbox bool
|
||||||
HasEnableSeccomp bool
|
HasEnableSeccomp bool
|
||||||
|
HasOutboundAddr bool
|
||||||
|
HasIPv6 bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type slirp4netnsCmdArg struct {
|
type slirp4netnsCmdArg struct {
|
||||||
@ -197,6 +199,8 @@ func checkSlirpFlags(path string) (*slirpFeatures, error) {
|
|||||||
HasMTU: strings.Contains(string(out), "--mtu"),
|
HasMTU: strings.Contains(string(out), "--mtu"),
|
||||||
HasEnableSandbox: strings.Contains(string(out), "--enable-sandbox"),
|
HasEnableSandbox: strings.Contains(string(out), "--enable-sandbox"),
|
||||||
HasEnableSeccomp: strings.Contains(string(out), "--enable-seccomp"),
|
HasEnableSeccomp: strings.Contains(string(out), "--enable-seccomp"),
|
||||||
|
HasOutboundAddr: strings.Contains(string(out), "--outbound-addr"),
|
||||||
|
HasIPv6: strings.Contains(string(out), "--enable-ipv6"),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,21 +229,64 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
|
|||||||
|
|
||||||
isSlirpHostForward := false
|
isSlirpHostForward := false
|
||||||
disableHostLoopback := true
|
disableHostLoopback := true
|
||||||
|
enableIPv6 := false
|
||||||
|
outboundAddr := ""
|
||||||
|
outboundAddr6 := ""
|
||||||
|
|
||||||
if ctr.config.NetworkOptions != nil {
|
if ctr.config.NetworkOptions != nil {
|
||||||
slirpOptions := ctr.config.NetworkOptions["slirp4netns"]
|
slirpOptions := ctr.config.NetworkOptions["slirp4netns"]
|
||||||
for _, o := range slirpOptions {
|
for _, o := range slirpOptions {
|
||||||
switch o {
|
parts := strings.Split(o, "=")
|
||||||
case "port_handler=slirp4netns":
|
option, value := parts[0], parts[1]
|
||||||
|
|
||||||
|
switch option {
|
||||||
|
case "port_handler":
|
||||||
|
switch value {
|
||||||
|
case "slirp4netns":
|
||||||
isSlirpHostForward = true
|
isSlirpHostForward = true
|
||||||
case "port_handler=rootlesskit":
|
case "rootlesskit":
|
||||||
isSlirpHostForward = false
|
isSlirpHostForward = false
|
||||||
case "allow_host_loopback=true":
|
default:
|
||||||
|
return errors.Errorf("unknown port_handler for slirp4netns: %q", value)
|
||||||
|
}
|
||||||
|
case "allow_host_loopback":
|
||||||
|
switch value {
|
||||||
|
case "true":
|
||||||
disableHostLoopback = false
|
disableHostLoopback = false
|
||||||
case "allow_host_loopback=false":
|
case "false":
|
||||||
disableHostLoopback = true
|
disableHostLoopback = true
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value of allow_host_loopback for slirp4netns: %q", value)
|
||||||
|
}
|
||||||
|
case "enable_ipv6":
|
||||||
|
switch value {
|
||||||
|
case "true":
|
||||||
|
enableIPv6 = true
|
||||||
|
case "false":
|
||||||
|
enableIPv6 = false
|
||||||
|
default:
|
||||||
|
return errors.Errorf("invalid value of enable_ipv6 for slirp4netns: %q", value)
|
||||||
|
}
|
||||||
|
case "outbound_addr":
|
||||||
|
ipv4 := net.ParseIP(value)
|
||||||
|
if ipv4 == nil || ipv4.To4() == nil {
|
||||||
|
_, err := net.InterfaceByName(value)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Errorf("invalid outbound_addr %q", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outboundAddr = value
|
||||||
|
case "outbound_addr6":
|
||||||
|
ipv6 := net.ParseIP(value)
|
||||||
|
if ipv6 == nil || ipv6.To4() != nil {
|
||||||
|
_, err := net.InterfaceByName(value)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Errorf("invalid outbound_addr6: %q", value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outboundAddr6 = value
|
||||||
default:
|
default:
|
||||||
return errors.Errorf("unknown option for slirp4netns: %q", o)
|
return errors.Errorf("unknown option for slirp4netns: %q", o)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,6 +309,30 @@ func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
|
|||||||
cmdArgs = append(cmdArgs, "--enable-seccomp")
|
cmdArgs = append(cmdArgs, "--enable-seccomp")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if enableIPv6 {
|
||||||
|
if !slirpFeatures.HasIPv6 {
|
||||||
|
return errors.Errorf("enable_ipv6 not supported")
|
||||||
|
}
|
||||||
|
cmdArgs = append(cmdArgs, "--enable-ipv6")
|
||||||
|
}
|
||||||
|
|
||||||
|
if outboundAddr != "" {
|
||||||
|
if !slirpFeatures.HasOutboundAddr {
|
||||||
|
return errors.Errorf("outbound_addr not supported")
|
||||||
|
}
|
||||||
|
cmdArgs = append(cmdArgs, fmt.Sprintf("--outbound-addr=%s", outboundAddr))
|
||||||
|
}
|
||||||
|
|
||||||
|
if outboundAddr6 != "" {
|
||||||
|
if !slirpFeatures.HasOutboundAddr || !slirpFeatures.HasIPv6 {
|
||||||
|
return errors.Errorf("outbound_addr6 not supported")
|
||||||
|
}
|
||||||
|
if !enableIPv6 {
|
||||||
|
return errors.Errorf("enable_ipv6=true is required for outbound_addr6")
|
||||||
|
}
|
||||||
|
cmdArgs = append(cmdArgs, fmt.Sprintf("--outbound-addr6=%s", outboundAddr6))
|
||||||
|
}
|
||||||
|
|
||||||
var apiSocket string
|
var apiSocket string
|
||||||
if havePortMapping && isSlirpHostForward {
|
if havePortMapping && isSlirpHostForward {
|
||||||
apiSocket = filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("%s.net", ctr.config.ID))
|
apiSocket = filepath.Join(ctr.runtime.config.Engine.TmpDir, fmt.Sprintf("%s.net", ctr.config.ID))
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
. "github.com/containers/podman/v2/test/utils"
|
. "github.com/containers/podman/v2/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
"github.com/uber/jaeger-client-go/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = Describe("Podman run networking", func() {
|
var _ = Describe("Podman run networking", func() {
|
||||||
@ -290,6 +293,53 @@ var _ = Describe("Podman run networking", func() {
|
|||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman run network bind to 127.0.0.1", func() {
|
||||||
|
slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
|
||||||
|
Expect(slirp4netnsHelp.ExitCode()).To(Equal(0))
|
||||||
|
networkConfiguration := "slirp4netns:outbound_addr=127.0.0.1,allow_host_loopback=true"
|
||||||
|
|
||||||
|
if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
|
||||||
|
ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8083"})
|
||||||
|
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"})
|
||||||
|
session.Wait(30)
|
||||||
|
ncListener.Wait(30)
|
||||||
|
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(ncListener.ExitCode()).To(Equal(0))
|
||||||
|
Expect(ncListener.ErrorToString()).To(ContainSubstring("127.0.0.1"))
|
||||||
|
} else {
|
||||||
|
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8083"})
|
||||||
|
session.Wait(30)
|
||||||
|
Expect(session.ExitCode()).ToNot(Equal(0))
|
||||||
|
Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("podman run network bind to HostIP", func() {
|
||||||
|
ip, err := utils.HostIP()
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
|
slirp4netnsHelp := SystemExec("slirp4netns", []string{"--help"})
|
||||||
|
Expect(slirp4netnsHelp.ExitCode()).To(Equal(0))
|
||||||
|
networkConfiguration := fmt.Sprintf("slirp4netns:outbound_addr=%s,allow_host_loopback=true", ip.String())
|
||||||
|
|
||||||
|
if strings.Contains(slirp4netnsHelp.OutputToString(), "outbound-addr") {
|
||||||
|
ncListener := StartSystemExec("nc", []string{"-v", "-n", "-l", "-p", "8084"})
|
||||||
|
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"})
|
||||||
|
session.Wait(30)
|
||||||
|
ncListener.Wait(30)
|
||||||
|
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
Expect(ncListener.ExitCode()).To(Equal(0))
|
||||||
|
Expect(ncListener.ErrorToString()).To(ContainSubstring(ip.String()))
|
||||||
|
} else {
|
||||||
|
session := podmanTest.Podman([]string{"run", "--network", networkConfiguration, "-dt", ALPINE, "nc", "-w", "2", "10.0.2.2", "8084"})
|
||||||
|
session.Wait(30)
|
||||||
|
Expect(session.ExitCode()).ToNot(Equal(0))
|
||||||
|
Expect(session.ErrorToString()).To(ContainSubstring("outbound_addr not supported"))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
It("podman run network expose ports in image metadata", func() {
|
It("podman run network expose ports in image metadata", func() {
|
||||||
session := podmanTest.Podman([]string{"create", "--name", "test", "-dt", "-P", nginx})
|
session := podmanTest.Podman([]string{"create", "--name", "test", "-dt", "-P", nginx})
|
||||||
session.Wait(90)
|
session.Wait(90)
|
||||||
|
@ -345,6 +345,16 @@ func SystemExec(command string, args []string) *PodmanSession {
|
|||||||
return &PodmanSession{session}
|
return &PodmanSession{session}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartSystemExec is used to start exec a system command
|
||||||
|
func StartSystemExec(command string, args []string) *PodmanSession {
|
||||||
|
c := exec.Command(command, args...)
|
||||||
|
session, err := gexec.Start(c, GinkgoWriter, GinkgoWriter)
|
||||||
|
if err != nil {
|
||||||
|
Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
|
||||||
|
}
|
||||||
|
return &PodmanSession{session}
|
||||||
|
}
|
||||||
|
|
||||||
// StringInSlice determines if a string is in a string slice, returns bool
|
// StringInSlice determines if a string is in a string slice, returns bool
|
||||||
func StringInSlice(s string, sl []string) bool {
|
func StringInSlice(s string, sl []string) bool {
|
||||||
for _, i := range sl {
|
for _, i := range sl {
|
||||||
|
Reference in New Issue
Block a user