mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 16:39:58 +00:00
TUN-7360: Add Get Host Details handler in management service
With the management tunnels work, we allow calls to our edge service using an access JWT provided by Tunnelstore. Given a connector ID, this request is then proxied to the appropriate Cloudflare Tunnel. This PR takes advantage of this flow and adds a new host_details endpoint. Calls to this endpoint will result in cloudflared gathering some details about the host: hostname (os.hostname()) and ip address (localAddr in a dial). Note that the mini spec lists 4 alternatives and this picks alternative 3 because: 1. Ease of implementation: This is quick and non-intrusive to any of our code path. We expect to change how connection tracking works and regardless of the direction we take, it may be easy to keep, morph or throw this away. 2. The cloudflared part of this round trip takes some time with a hostname call and a dial. But note that this is off the critical path and not an API that will be exercised often.
This commit is contained in:
@@ -2,12 +2,15 @@ package management
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
@@ -29,6 +32,9 @@ type ManagementService struct {
|
||||
// The management tunnel hostname
|
||||
Hostname string
|
||||
|
||||
serviceIP string
|
||||
clientID uuid.UUID
|
||||
|
||||
log *zerolog.Logger
|
||||
router chi.Router
|
||||
|
||||
@@ -42,16 +48,24 @@ type ManagementService struct {
|
||||
logger LoggerListener
|
||||
}
|
||||
|
||||
func New(managementHostname string, log *zerolog.Logger, logger LoggerListener) *ManagementService {
|
||||
func New(managementHostname string,
|
||||
serviceIP string,
|
||||
clientID uuid.UUID,
|
||||
log *zerolog.Logger,
|
||||
logger LoggerListener,
|
||||
) *ManagementService {
|
||||
s := &ManagementService{
|
||||
Hostname: managementHostname,
|
||||
log: log,
|
||||
logger: logger,
|
||||
Hostname: managementHostname,
|
||||
log: log,
|
||||
logger: logger,
|
||||
serviceIP: serviceIP,
|
||||
clientID: clientID,
|
||||
}
|
||||
r := chi.NewRouter()
|
||||
r.Get("/ping", ping)
|
||||
r.Head("/ping", ping)
|
||||
r.Get("/logs", s.logs)
|
||||
r.Get("/host_details", s.getHostDetails)
|
||||
s.router = r
|
||||
return s
|
||||
}
|
||||
@@ -65,6 +79,42 @@ func ping(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
}
|
||||
|
||||
// The response provided by the /host_details endpoint
|
||||
type getHostDetailsResponse struct {
|
||||
ClientID string `json:"connector_id"`
|
||||
IP string `json:"ip,omitempty"`
|
||||
HostName string `json:"hostname,omitempty"`
|
||||
}
|
||||
|
||||
func (m *ManagementService) getHostDetails(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var getHostDetailsResponse = getHostDetailsResponse{
|
||||
ClientID: m.clientID.String(),
|
||||
}
|
||||
if ip, err := getPrivateIP(m.serviceIP); err == nil {
|
||||
getHostDetailsResponse.IP = ip
|
||||
}
|
||||
if hostname, err := os.Hostname(); err == nil {
|
||||
getHostDetailsResponse.HostName = hostname
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(200)
|
||||
json.NewEncoder(w).Encode(getHostDetailsResponse)
|
||||
}
|
||||
|
||||
// Get preferred private ip of this machine
|
||||
func getPrivateIP(addr string) (string, error) {
|
||||
conn, err := net.DialTimeout("tcp", addr, 1*time.Second)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer conn.Close()
|
||||
localAddr := conn.LocalAddr().String()
|
||||
host, _, err := net.SplitHostPort(localAddr)
|
||||
return host, err
|
||||
}
|
||||
|
||||
// readEvents will loop through all incoming websocket messages from a client and marshal them into the
|
||||
// proper Event structure and pass through to the events channel. Any invalid messages sent will automatically
|
||||
// terminate the connection.
|
||||
|
Reference in New Issue
Block a user