mirror of
https://github.com/containers/gvisor-tap-vsock.git
synced 2025-12-24 13:29:22 +08:00
Add endpoint to configure port forwarding without going to the host
This commit is contained in:
@@ -37,6 +37,8 @@ var (
|
||||
exitCode int
|
||||
)
|
||||
|
||||
const gatewayIP = "192.168.127.1"
|
||||
|
||||
func main() {
|
||||
flag.Var(&endpoints, "listen", fmt.Sprintf("URL where the tap send packets (default %s)", transport.DefaultURL))
|
||||
flag.BoolVar(&debug, "debug", false, "Print debug info")
|
||||
@@ -107,7 +109,7 @@ func main() {
|
||||
CaptureFile: captureFile(),
|
||||
MTU: mtu,
|
||||
Subnet: "192.168.127.0/24",
|
||||
GatewayIP: "192.168.127.1",
|
||||
GatewayIP: gatewayIP,
|
||||
GatewayMacAddress: "5a:94:ef:e4:0c:dd",
|
||||
DHCPStaticLeases: map[string]string{
|
||||
"192.168.127.2": "5a:94:ef:e4:0c:ee",
|
||||
@@ -118,7 +120,7 @@ func main() {
|
||||
Records: []types.Record{
|
||||
{
|
||||
Name: "gateway",
|
||||
IP: net.ParseIP("192.168.127.1"),
|
||||
IP: net.ParseIP(gatewayIP),
|
||||
},
|
||||
{
|
||||
Name: "host",
|
||||
@@ -131,7 +133,7 @@ func main() {
|
||||
Records: []types.Record{
|
||||
{
|
||||
Name: "gateway",
|
||||
IP: net.ParseIP("192.168.127.1"),
|
||||
IP: net.ParseIP(gatewayIP),
|
||||
},
|
||||
{
|
||||
Name: "host",
|
||||
@@ -207,21 +209,19 @@ func run(ctx context.Context, g *errgroup.Group, configuration *types.Configurat
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot listen")
|
||||
}
|
||||
g.Go(func() error {
|
||||
<-ctx.Done()
|
||||
return ln.Close()
|
||||
})
|
||||
g.Go(func() error {
|
||||
err := http.Serve(ln, withProfiler(vn))
|
||||
if err != nil {
|
||||
if err != http.ErrServerClosed {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
httpServe(ctx, g, ln, withProfiler(vn))
|
||||
}
|
||||
|
||||
ln, err := vn.Listen("tcp", fmt.Sprintf("%s:80", gatewayIP))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/services/forwarder/all", vn.Mux())
|
||||
mux.Handle("/services/forwarder/expose", vn.Mux())
|
||||
mux.Handle("/services/forwarder/unexpose", vn.Mux())
|
||||
httpServe(ctx, g, ln, mux)
|
||||
|
||||
if debug {
|
||||
g.Go(func() error {
|
||||
debugLog:
|
||||
@@ -290,6 +290,23 @@ func run(ctx context.Context, g *errgroup.Group, configuration *types.Configurat
|
||||
return nil
|
||||
}
|
||||
|
||||
func httpServe(ctx context.Context, g *errgroup.Group, ln net.Listener, mux http.Handler) {
|
||||
g.Go(func() error {
|
||||
<-ctx.Done()
|
||||
return ln.Close()
|
||||
})
|
||||
g.Go(func() error {
|
||||
err := http.Serve(ln, mux)
|
||||
if err != nil {
|
||||
if err != http.ErrServerClosed {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func withProfiler(vn *virtualnetwork.VirtualNetwork) http.Handler {
|
||||
mux := vn.Mux()
|
||||
if debug {
|
||||
|
||||
@@ -160,7 +160,12 @@ func (f *PortsForwarder) Mux() http.Handler {
|
||||
if req.Protocol == "" {
|
||||
req.Protocol = types.TCP
|
||||
}
|
||||
if err := f.Expose(req.Protocol, req.Local, req.Remote); err != nil {
|
||||
remote, err := remote(req, r.RemoteAddr)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := f.Expose(req.Protocol, req.Local, remote); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -187,3 +192,19 @@ func (f *PortsForwarder) Mux() http.Handler {
|
||||
})
|
||||
return mux
|
||||
}
|
||||
|
||||
// if the request doesn't have an IP in the remote field, use the IP from the incoming http request.
|
||||
func remote(req types.ExposeRequest, ip string) (string, error) {
|
||||
remoteIP, _, err := net.SplitHostPort(req.Remote)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if remoteIP == "" {
|
||||
host, _, err := net.SplitHostPort(ip)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s%s", host, req.Remote), nil
|
||||
}
|
||||
return req.Remote, nil
|
||||
}
|
||||
|
||||
@@ -141,4 +141,33 @@ address=/foobar/1.2.3.4
|
||||
g.Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
}).Should(Succeed())
|
||||
})
|
||||
|
||||
It("should reach a http server in the VM using dynamic port forwarding configured within the VM", func() {
|
||||
_, err := sshExec("sudo podman run --rm --name http-test -d -p 8080:80 -t docker.io/library/nginx:alpine")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
defer func() {
|
||||
_, err := sshExec("sudo podman stop http-test")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
}()
|
||||
|
||||
_, err = net.Dial("tcp", "127.0.0.1:9090")
|
||||
Expect(err.Error()).To(HaveSuffix("connection refused"))
|
||||
|
||||
_, err = sshExec(`curl http://gateway.containers.internal/services/forwarder/expose -X POST -d'{"local":":9090", "remote":":8080"}'`)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Eventually(func(g Gomega) {
|
||||
resp, err := http.Get("http://127.0.0.1:9090")
|
||||
g.Expect(err).ShouldNot(HaveOccurred())
|
||||
g.Expect(resp.StatusCode).To(Equal(http.StatusOK))
|
||||
}).Should(Succeed())
|
||||
|
||||
_, err = sshExec(`curl http://gateway.containers.internal/services/forwarder/unexpose -X POST -d'{"local":":9090"}'`)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
|
||||
Eventually(func(g Gomega) {
|
||||
_, err = net.Dial("tcp", "127.0.0.1:9090")
|
||||
g.Expect(err.Error()).To(HaveSuffix("connection refused"))
|
||||
}).Should(Succeed())
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user