Skip to content

Commit

Permalink
Block port checks for private/loopback/unspecificed/invalid operator IPs
Browse files Browse the repository at this point in the history
  • Loading branch information
pschork committed Apr 27, 2024
1 parent 1063b0a commit 2e697bd
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 22 deletions.
48 changes: 33 additions & 15 deletions disperser/dataapi/operator_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func checkIsOnlineAndProcessOperator(operatorStatus OperatorOnlineStatus, operat
var socket string
if operatorStatus.IndexedOperatorInfo != nil {
socket = core.OperatorSocket(operatorStatus.IndexedOperatorInfo.Socket).GetRetrievalSocket()
isOnline = checkIsOperatorOnline(socket)
isOnline = checkIsOperatorOnline(socket, 10, logger)
}

// Log the online status
Expand All @@ -104,42 +104,60 @@ func checkIsOnlineAndProcessOperator(operatorStatus OperatorOnlineStatus, operat
operatorOnlineStatusresultsChan <- metadata
}

func validOperatorIP(socketString string) bool {
ip, _, _, err := core.ParseOperatorSocket(socketString)
if err != nil {
return true
}
ipAddr := net.ParseIP(ip)
if ipAddr == nil {
return true
}
return ipAddr.IsPrivate() || !ipAddr.IsUnspecified() || !ipAddr.IsLoopback()
}

func (s *server) probeOperatorPorts(ctx context.Context, operatorId string) (*OperatorPortCheckResponse, error) {
operatorInfo, err := s.subgraphClient.QueryOperatorInfoByOperatorId(context.Background(), operatorId)
if err != nil {
s.logger.Warn("Failed to fetch operator info", "error", err)
s.logger.Warn("failed to fetch operator info", "error", err)
return &OperatorPortCheckResponse{}, errors.New("not found")
}

retrieverSocket := core.OperatorSocket(operatorInfo.Socket).GetRetrievalSocket()
retrieverOnline := checkIsOperatorOnline(retrieverSocket)
operatorSocket := core.OperatorSocket(operatorInfo.Socket)
retrievalSocket := operatorSocket.GetRetrievalSocket()
retrievalOnline := checkIsOperatorOnline(retrievalSocket, 3, s.logger)

disperserSocket := core.OperatorSocket(operatorInfo.Socket).GetDispersalSocket()
disperserOnline := checkIsOperatorOnline(disperserSocket)

// Log the online status
s.logger.Info("Operator port status", "retrieverOnline", retrieverOnline, "retrieverSocket", retrieverSocket, "disperserOnline", disperserOnline, "disperserSocket", disperserSocket)
dispersalSocket := operatorSocket.GetDispersalSocket()
dispersalOnline := checkIsOperatorOnline(dispersalSocket, 3, s.logger)

// Create the metadata regardless of online status
portCheckResponse := &OperatorPortCheckResponse{
OperatorId: operatorId,
DisperserSocket: disperserSocket,
RetrieverSocket: retrieverSocket,
DisperserOnline: disperserOnline,
RetrieverOnline: retrieverOnline,
DispersalSocket: dispersalSocket,
RetrievalSocket: retrievalSocket,
DispersalOnline: dispersalOnline,
RetrievalOnline: retrievalOnline,
}

// Log the online status
s.logger.Info("operator port check response", portCheckResponse)

// Send the metadata to the results channel
return portCheckResponse, nil
}

// method to check if operator is online
// Note: This method is least intrusive way to check if operator is online
// AlternateSolution: Should we add an endpt to check if operator is online?
func checkIsOperatorOnline(socket string) bool {
timeout := time.Second * 10
func checkIsOperatorOnline(socket string, timeoutSecs int, logger logging.Logger) bool {
if !validOperatorIP(socket) {
logger.Error("port check blocked invalid operator IP", "socket", socket)
return false
}
timeout := time.Second * time.Duration(timeoutSecs)
conn, err := net.DialTimeout("tcp", socket, timeout)
if err != nil {
logger.Warn("port check timeout", "socket", socket, "timeout", timeoutSecs, "error", err)
return false
}
defer conn.Close() // Close the connection after checking
Expand Down
14 changes: 7 additions & 7 deletions disperser/dataapi/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ type (

OperatorPortCheckResponse struct {
OperatorId string `json:"operator_id"`
DisperserSocket string `json:"disperser_socket"`
RetrieverSocket string `json:"retriever_socket"`
DisperserOnline bool `json:"disperser_online"`
RetrieverOnline bool `json:"retriever_online"`
DispersalSocket string `json:"dispersal_socket"`
RetrievalSocket string `json:"retrieval_socket"`
DispersalOnline bool `json:"dispersal_online"`
RetrievalOnline bool `json:"retrieval_online"`
}
ErrorResponse struct {
Error string `json:"error"`
Expand Down Expand Up @@ -688,15 +688,15 @@ func (s *server) OperatorPortCheck(c *gin.Context) {
defer timer.ObserveDuration()

operatorId := c.DefaultQuery("operator_id", "")
s.logger.Info("Checking operator ports", "operatorId", operatorId)
s.logger.Info("checking operator ports", "operatorId", operatorId)
portCheckResponse, err := s.probeOperatorPorts(c.Request.Context(), operatorId)
if err != nil {
if strings.Contains(err.Error(), "not found") {
err = errNotFound
s.logger.Warn("Operator not found", "operatorId", operatorId)
s.logger.Warn("operator not found", "operatorId", operatorId)
s.metrics.IncrementNotFoundRequestNum("OperatorPortCheck")
} else {
s.logger.Error("Operator port check failed", "error", err)
s.logger.Error("operator port check failed", "error", err)
s.metrics.IncrementFailedRequestNum("OperatorPortCheck")
}
errorResponse(c, err)
Expand Down

0 comments on commit 2e697bd

Please sign in to comment.