-
Notifications
You must be signed in to change notification settings - Fork 112
Add pesto support for dynamic port forwarding via pasta control socket
#755
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
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| // Pesto client for dynamic port forwarding on a running pasta instance. | ||
|
Honny1 marked this conversation as resolved.
|
||
| // | ||
| // Pesto updates pasta's forwarding table via a UNIX domain socket (-c). | ||
| // Used by rootless bridge networking: pesto incrementally adds or deletes | ||
| // port forwarding rules for individual containers. | ||
| // | ||
| // Passt only forwards traffic from the host into the rootless netns. | ||
| // Netavark handles the final DNAT to the container IP:ContainerPort | ||
| // inside the netns. Each mapping uses HostPort as both source and | ||
| // destination so traffic arrives at the port netavark expects. | ||
| // | ||
| // When no HostIP is specified, pesto binds both IPv4 (0.0.0.0) and | ||
| // IPv6 ([::]) so dual-stack networks work out of the box. | ||
| // | ||
| // Limitations: | ||
| // - TCP and UDP only (SCTP is silently skipped) | ||
|
|
||
| package pasta | ||
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
| "os/exec" | ||
| "strings" | ||
|
|
||
| "github.com/sirupsen/logrus" | ||
| "go.podman.io/common/libnetwork/types" | ||
| "go.podman.io/common/pkg/config" | ||
| ) | ||
|
|
||
| const PestoBinaryName = "pesto" | ||
|
|
||
| // PestoAddPorts adds port forwarding rules to the running pasta instance | ||
| // via -A/--add. Idempotent: adding already-active ports is a no-op. | ||
| func PestoAddPorts(conf *config.Config, socketPath string, ports []types.PortMapping) error { | ||
| if socketPath == "" { | ||
| return errors.New("pesto control socket not available") | ||
| } | ||
| logrus.Debugf("pesto: adding %d port mappings", len(ports)) | ||
| return pestoModifyPorts(conf, socketPath, ports, "--add") | ||
| } | ||
|
|
||
| // PestoDeletePorts removes port forwarding rules from the running pasta | ||
| // instance via -D/--delete. | ||
| func PestoDeletePorts(conf *config.Config, socketPath string, ports []types.PortMapping) error { | ||
| if socketPath == "" { | ||
| return nil | ||
| } | ||
| logrus.Debugf("pesto: deleting %d port mappings", len(ports)) | ||
| return pestoModifyPorts(conf, socketPath, ports, "--delete") | ||
| } | ||
|
|
||
| func pestoModifyPorts(conf *config.Config, socketPath string, ports []types.PortMapping, mode string) error { | ||
| pestoPath, err := conf.FindHelperBinary(PestoBinaryName, true) | ||
| if err != nil { | ||
| return fmt.Errorf("could not find pesto binary: %w", err) | ||
| } | ||
|
|
||
| pestoArgs, err := portMappingsToPestoArgs(ports) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| args := make([]string, 0, len(pestoArgs)+2) // +2 for mode and socket path | ||
| args = append(args, mode) | ||
| args = append(args, pestoArgs...) | ||
| args = append(args, socketPath) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can socketPath == ""
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it cannot be. It should be checked by the caller. Should I add a check to be sure? |
||
|
|
||
| logrus.Debugf("pesto arguments: %s", strings.Join(args, " ")) | ||
|
|
||
| out, err := exec.Command(pestoPath, args...).CombinedOutput() | ||
| if err != nil { | ||
| return fmt.Errorf("pesto failed: %w\noutput: %s", err, string(out)) | ||
| } | ||
| if len(out) > 0 { | ||
| logrus.Debugf("pesto output: %s", strings.TrimSpace(string(out))) | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| // portMappingsToPestoArgs converts PortMappings into pesto CLI arguments. | ||
| // | ||
| // When HostIP is set, a single binding is created (e.g. "-t 127.0.0.1/8080"). | ||
| // When HostIP is empty, both IPv4 and IPv6 bindings are created so that | ||
| // dual-stack networks work: "-t 0.0.0.0/8080 -t [::]/8080". | ||
| func portMappingsToPestoArgs(ports []types.PortMapping) ([]string, error) { | ||
| var args []string | ||
|
|
||
| for _, p := range ports { | ||
| var addrs []string | ||
| switch { | ||
| case p.HostIP == "": | ||
| addrs = []string{"0.0.0.0/", "[::]/"} | ||
| case strings.Contains(p.HostIP, ":"): | ||
| addrs = []string{"[" + p.HostIP + "]/"} | ||
| default: | ||
| addrs = []string{p.HostIP + "/"} | ||
| } | ||
|
|
||
| for protocol := range strings.SplitSeq(p.Protocol, ",") { | ||
| var flag string | ||
| switch protocol { | ||
| case "tcp": | ||
| flag = "-t" | ||
| case "udp": | ||
| flag = "-u" | ||
| default: | ||
| return nil, fmt.Errorf("pesto: unsupported protocol %s", protocol) | ||
| } | ||
|
|
||
| portRange := p.Range | ||
| if portRange == 0 { | ||
| portRange = 1 | ||
| } | ||
|
|
||
| for _, addr := range addrs { | ||
| var arg string | ||
| if portRange == 1 { | ||
| arg = fmt.Sprintf("%s%d", addr, p.HostPort) | ||
| } else { | ||
| arg = fmt.Sprintf("%s%d-%d", addr, p.HostPort, p.HostPort+portRange-1) | ||
| } | ||
| args = append(args, flag, arg) | ||
| } | ||
| } | ||
| } | ||
| return args, nil | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a change for this PR, but it would be nice to have a follow-up that puts these in alpha order.