-
Notifications
You must be signed in to change notification settings - Fork 638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Port forwarding doesn't work for non-127.0.0.1 localhost #3539
Comments
@AkihiroSuda tag From a glance, I am not sure this can be solved inside nerdctl. |
This is probably a bug of https://github.com/rootless-containers/rootlesskit. Workarounds:
|
it is not bug. The default |
In the current implementation, when On the other hand, Rootlesskit Child NetNS will send the request to However, that is the expected behavior as described in the document below.
QuestionI think propagation of the ip that is accept() in Parent NetNS to Child NetNS will solve this problem, so I'll create a PR in rootlesskit for propagation of parent ip to improve the behavior of this issue. What do you think? |
Thanks, does your PR pass the nerdctl CI? |
Thanks for your efforts but I'm not sure how you plan to forward traffic from a child network namespace to the host network while preserving the source IP address when using the |
Thanks for comments !!!
When I locally apply the modification that is trying to create a PR, Details
[ec2-user@ip-172-31-40-91 rootlesskit]$ make && sudo make install
make: Nothing to be done for 'all'.
install -D -m 755 /home/ec2-user/rootlesskit/bin/rootlesskit /usr/local/bin/rootlesskit
install -D -m 755 /home/ec2-user/rootlesskit/bin/rootlessctl /usr/local/bin/rootlessctl
install -D -m 755 /home/ec2-user/rootlesskit/bin/rootlesskit-docker-proxy /usr/local/bin/rootlesskit-docker-proxy
[ec2-user@ip-172-31-40-91 rootlesskit]$ sudo systemctl restart user@1000.service
[ec2-user@ip-172-31-40-91 rootlesskit]$ n rm -f nginx && nerdctl run -d --name nginx -p 127.0.0.2:8080:80 nginx && nerdctl ps
nginx
72824134f1fb2d642ce386642f7229316a400ce927025605c4f4decc5cf3a7fd
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
72824134f1fb docker.io/library/nginx:latest "/docker-entrypoint.…" Less than a second ago Up 127.0.0.2:8080->80/tcp nginx
[ec2-user@ip-172-31-40-91 rootlesskit]$ curl 127.0.0.2:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html> As for CI, I haven't been able to confirm this yet, so I'll check.
When Parent NetNS sends a request to Child NetNS, the following processing is performed. This I haven't written the PR yet, but the diff is as follows. Details
[ec2-user@ip-172-31-40-91 rootlesskit]$ gd
diff --git a/pkg/port/builtin/child/child.go b/pkg/port/builtin/child/child.go
index 83ab638..ebcdc67 100644
--- a/pkg/port/builtin/child/child.go
+++ b/pkg/port/builtin/child/child.go
@@ -122,7 +122,8 @@ func (d *childDriver) handleConnectRequest(c *net.UnixConn, req *msg.Request) er
var dialer net.Dialer
ip := req.IP
if ip == "" {
- ip = "127.0.0.1"
+ // ip = "127.0.0.1"
+ ip = req.ParentIP
} else {
p := net.ParseIP(ip)
if p == nil {
diff --git a/pkg/port/builtin/msg/msg.go b/pkg/port/builtin/msg/msg.go
index f77468e..4b07161 100644
--- a/pkg/port/builtin/msg/msg.go
+++ b/pkg/port/builtin/msg/msg.go
@@ -19,10 +19,11 @@ const (
// Request and Response are encoded as JSON with uint32le length header.
type Request struct {
- Type string // "init" or "connect"
- Proto string // "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6"
- IP string
- Port int
+ Type string // "init" or "connect"
+ Proto string // "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6"
+ IP string
+ Port int
+ ParentIP string
}
// Reply may contain FD as OOB
@@ -52,10 +53,11 @@ func Initiate(c *net.UnixConn) error {
// that corresponds to the port spec.
func ConnectToChild(c *net.UnixConn, spec port.Spec) (int, error) {
req := Request{
- Type: RequestTypeConnect,
- Proto: spec.Proto,
- Port: spec.ChildPort,
- IP: spec.ChildIP,
+ Type: RequestTypeConnect,
+ Proto: spec.Proto,
+ Port: spec.ChildPort,
+ IP: spec.ChildIP,
+ ParentIP: spec.ParentIP,
}
if _, err := lowlevelmsgutil.MarshalToWriter(c, &req); err != nil {
return 0, err |
When containerd is running as a root user and an address other than `127.0.0.1`, such as `127.0.0.2`, is specified in `-p` when `nerdctl run` is used to start a container, the combination of the address and port number allows connections to an application running in the container. Specifically, `curl 127.0.0.2:8080` will access a nginx application running on port `80` in the container created by the following command. ``` $ sudo nerdctl run --name nginx -d -p 127.0.0.2:8080:80 nginx 7abce48d42ef809613365ffaa54d9526e8388c78f5f5c2d8a2850628543ca27e $ sudo nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7abce48d42ef docker.io/library/nginx:latest "/docker-entrypoint.…" 3 seconds ago Up 127.0.0.2:8080->80/tcp nginx $ curl 127.0.0.2:8080 <!DOCTYPE html> ... ``` On the other hand, when running containerd as a non-root user, similarly, suppose we start a container with an address other than `127.0.0.1`, such as `127.0.0.2` for -p. In this case, curl `127.0.0.2:8080` will not connect to a nginx application running inside the container. Details are described below. ``` $ nerdctl run --name nginx -d -p 127.0.0.2:8080:80 nginx 7687f9612afe6847fb3946254718fafef935ffdc05f9cbb4496fc40dd35a6abc $ nerdctl ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7687f9612afe docker.io/library/nginx:latest "/docker-entrypoint.…" 5 seconds ago Up 127.0.0.2:8080->80/tcp nginx $ curl 127.0.0.2:8080 curl: (56) Recv failure: Connection reset by peer ``` When a connection is requested from the outside to the container in Parent NetNS, the rootlesskit port driver relays the connection from Parent NetNS to Child NetNS. When, for example, an address such as `127.0.0.2` is specified in -p, Child NetNS need to establish a connection to the specified address. However, the current implementation will establish a connection to `127.0.0.1` even when `127.0.0.2` is specified in -p. The behavior of not propagating the address specified by -p is assumed at this time, as described in the following document. - https://github.com/rootless-containers/rootlesskit/blob/master/docs/port.md#port-drivers > --port-driver Throughput Source IP > ... > builtin 30.0 Gbps Always 127.0.0.1 > ... > The builtin driver is fast, but be aware that the source IP is not propagated and always set to 127.0.0.1. However, an issue to improve this behavior is reported below. - containerd/nerdctl#3539 Therefore, this commit fixes when running containerd as a non-root user, the address specified in -p will be propagated. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
…in rootless mode When running a rootless container, specifying an address such as 127.0.0.2 for the -p option, we will not be able to access the published container through that address. This behavior is reported in the following issue: - containerd#3539 This behavior is caused by the behavior in rootlesskit, and the following pull request has been made to improve the behavior. - rootless-containers/rootlesskit#477 Therefore, this commit adds a test to ensure that the behavior of the issue has been improved. Signed-off-by: Hayato Kiwata <haytok@amazon.co.jp>
I believe this is fixed with #3831, closing. Feel free to reopen if you still see the issue |
Description
nerdctl run --rm -p 127.0.0.2:8080:80 nginx
does not work as expected:nerdctl run --rm -p 127.0.0.1:8080:80 nginx
does work, and outputs the appropriate nginx welcome page fromcurl 127.0.0.1:8080
Can confirm (on another Linux box) that the same functionality (listen on
127.0.0.2:8080
) works in rootless Podman.Note: the output for
nerdctl port
in general, seems reversed to what I would expect but contains the right address:ss
also confirms something is listening on the right address:Steps to reproduce the issue
1.Install and setup rootless nerdctl
2.Run
nerdctl run --rm -p 127.0.0.2:8080:80 nginx
3.Attempt
curl 127.0.0.2:8080
4.Get
reset by peer
Describe the results you received and expected
Received: reset by peer
Expected: to be connected to the service in the container
What version of nerdctl are you using?
nerdctl version 2.0.0-rc.2, rootless, Linux (Pop!_OS 22.04 LTS), install from tar
Are you using a variant of nerdctl? (e.g., Rancher Desktop)
None
Host information
The text was updated successfully, but these errors were encountered: