Merge pull request #429 from lstocchi/i425

Add --services flag to start API without using --listen flag
This commit is contained in:
openshift-merge-bot[bot]
2025-01-30 16:01:54 +00:00
committed by GitHub
3 changed files with 59 additions and 41 deletions

View File

@@ -112,7 +112,7 @@ With the executable:
### API
When `gvproxy` is started with the `--listen` option, it exposes a HTTP API on the host.
When `gvproxy` is started with the `--listen` or `--services` option, it exposes a HTTP API on the host.
This API can be used with curl.
```
@@ -127,6 +127,8 @@ $ curl --unix-socket /tmp/network.sock http:/unix/stats
...
```
N.B: The `--services` option exposes the same HTTP API as the `--listen` option, but without the `/connect` endpoint. This is useful for scenarios where the `gvforwarder`/`vm` tool is not run on the guest but you still want to expose services and stats endpoints.
### Gateway
The executable running on the host runs a virtual gateway that can be used by the VM.
@@ -144,7 +146,7 @@ nameserver 192.168.127.1
### Port forwarding
Dynamic port forwarding is supported over the host HTTP API when `gvproxy` was
started with `--listen`, but also in the VM over http://192.168.127.1:80.
started with `--listen` or `--services`, but also in the VM over http://192.168.127.1:80.
Expose a port:
```

View File

@@ -30,22 +30,23 @@ import (
)
var (
debug bool
mtu int
endpoints arrayFlags
vpnkitSocket string
qemuSocket string
bessSocket string
stdioSocket string
vfkitSocket string
forwardSocket arrayFlags
forwardDest arrayFlags
forwardUser arrayFlags
forwardIdentify arrayFlags
sshPort int
pidFile string
exitCode int
logFile string
debug bool
mtu int
endpoints arrayFlags
vpnkitSocket string
qemuSocket string
bessSocket string
stdioSocket string
vfkitSocket string
forwardSocket arrayFlags
forwardDest arrayFlags
forwardUser arrayFlags
forwardIdentify arrayFlags
sshPort int
pidFile string
exitCode int
logFile string
servicesEndpoint string
)
const (
@@ -74,6 +75,7 @@ func main() {
flag.Var(&forwardIdentify, "forward-identity", "Path to SSH identity key for forwarding")
flag.StringVar(&pidFile, "pid-file", "", "Generate a file with the PID in it")
flag.StringVar(&logFile, "log-file", "", "Output log messages (logrus) to a given file path")
flag.StringVar(&servicesEndpoint, "services", "", "Exposes the same HTTP API as the --listen flag, without the /connect endpoint")
flag.Parse()
if version.ShowVersion() {
@@ -262,7 +264,7 @@ func main() {
}
groupErrs.Go(func() error {
return run(ctx, groupErrs, &config, endpoints)
return run(ctx, groupErrs, &config, endpoints, servicesEndpoint)
})
// Wait for something to happen
@@ -310,7 +312,7 @@ func captureFile() string {
return "capture.pcap"
}
func run(ctx context.Context, g *errgroup.Group, configuration *types.Configuration, endpoints []string) error {
func run(ctx context.Context, g *errgroup.Group, configuration *types.Configuration, endpoints []string, servicesEndpoint string) error {
vn, err := virtualnetwork.New(configuration)
if err != nil {
return err
@@ -326,6 +328,15 @@ func run(ctx context.Context, g *errgroup.Group, configuration *types.Configurat
httpServe(ctx, g, ln, withProfiler(vn))
}
if servicesEndpoint != "" {
log.Infof("enabling services API. Listening %s", servicesEndpoint)
ln, err := transport.Listen(servicesEndpoint)
if err != nil {
return errors.Wrap(err, "cannot listen")
}
httpServe(ctx, g, ln, vn.ServicesMux())
}
ln, err := vn.Listen("tcp", fmt.Sprintf("%s:80", gatewayIP))
if err != nil {
return err

View File

@@ -15,7 +15,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
)
func (n *VirtualNetwork) Mux() *http.ServeMux {
func (n *VirtualNetwork) ServicesMux() *http.ServeMux {
mux := http.NewServeMux()
mux.Handle("/services/", http.StripPrefix("/services", n.servicesMux))
mux.HandleFunc("/stats", func(w http.ResponseWriter, _ *http.Request) {
@@ -27,26 +27,6 @@ func (n *VirtualNetwork) Mux() *http.ServeMux {
mux.HandleFunc("/leases", func(w http.ResponseWriter, _ *http.Request) {
_ = json.NewEncoder(w).Encode(n.ipPool.Leases())
})
mux.HandleFunc(types.ConnectPath, func(w http.ResponseWriter, _ *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
if err := bufrw.Flush(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_ = n.networkSwitch.Accept(context.Background(), conn, n.configuration.Protocol)
})
mux.HandleFunc("/tunnel", func(w http.ResponseWriter, r *http.Request) {
ip := r.URL.Query().Get("ip")
if ip == "" {
@@ -98,3 +78,28 @@ func (n *VirtualNetwork) Mux() *http.ServeMux {
})
return mux
}
func (n *VirtualNetwork) Mux() *http.ServeMux {
mux := n.ServicesMux()
mux.HandleFunc(types.ConnectPath, func(w http.ResponseWriter, _ *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "webserver doesn't support hijacking", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
if err := bufrw.Flush(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_ = n.networkSwitch.Accept(context.Background(), conn, n.configuration.Protocol)
})
return mux
}