mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-08-18 00:18:47 +00:00
TRA-4140 Fix HTTP/1.0 is recognized as HTTP/1.1 (#666)
This commit is contained in:
parent
d5fd2ff1da
commit
b31af7214b
@ -24,7 +24,7 @@ Think TCPDump and Wireshark re-invented for Kubernetes.
|
|||||||
|
|
||||||
- Simple and powerful CLI
|
- Simple and powerful CLI
|
||||||
- Monitoring network traffic in real-time. Supported protocols:
|
- Monitoring network traffic in real-time. Supported protocols:
|
||||||
- [HTTP/1.1](https://datatracker.ietf.org/doc/html/rfc2616) (REST, etc.)
|
- [HTTP/1.x](https://datatracker.ietf.org/doc/html/rfc2616) (REST, GraphQL, SOAP, etc.)
|
||||||
- [HTTP/2](https://datatracker.ietf.org/doc/html/rfc7540) (gRPC)
|
- [HTTP/2](https://datatracker.ietf.org/doc/html/rfc7540) (gRPC)
|
||||||
- [AMQP](https://www.rabbitmq.com/amqp-0-9-1-reference.html) (RabbitMQ, Apache Qpid, etc.)
|
- [AMQP](https://www.rabbitmq.com/amqp-0-9-1-reference.html) (RabbitMQ, Apache Qpid, etc.)
|
||||||
- [Apache Kafka](https://kafka.apache.org/protocol)
|
- [Apache Kafka](https://kafka.apache.org/protocol)
|
||||||
|
@ -66,7 +66,7 @@ func handleHTTP2Stream(http2Assembler *Http2Assembler, tcpID *api.TcpID, superTi
|
|||||||
streamID,
|
streamID,
|
||||||
"HTTP2",
|
"HTTP2",
|
||||||
)
|
)
|
||||||
item = reqResMatcher.registerRequest(ident, &messageHTTP1, superTimer.CaptureTime)
|
item = reqResMatcher.registerRequest(ident, &messageHTTP1, superTimer.CaptureTime, messageHTTP1.ProtoMinor)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
item.ConnectionInfo = &api.ConnectionInfo{
|
item.ConnectionInfo = &api.ConnectionInfo{
|
||||||
ClientIP: tcpID.SrcIP,
|
ClientIP: tcpID.SrcIP,
|
||||||
@ -86,7 +86,7 @@ func handleHTTP2Stream(http2Assembler *Http2Assembler, tcpID *api.TcpID, superTi
|
|||||||
streamID,
|
streamID,
|
||||||
"HTTP2",
|
"HTTP2",
|
||||||
)
|
)
|
||||||
item = reqResMatcher.registerResponse(ident, &messageHTTP1, superTimer.CaptureTime)
|
item = reqResMatcher.registerResponse(ident, &messageHTTP1, superTimer.CaptureTime, messageHTTP1.ProtoMinor)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
item.ConnectionInfo = &api.ConnectionInfo{
|
item.ConnectionInfo = &api.ConnectionInfo{
|
||||||
ClientIP: tcpID.DstIP,
|
ClientIP: tcpID.DstIP,
|
||||||
@ -135,7 +135,7 @@ func handleHTTP1ClientStream(b *bufio.Reader, tcpID *api.TcpID, counterPair *api
|
|||||||
counterPair.Request,
|
counterPair.Request,
|
||||||
"HTTP1",
|
"HTTP1",
|
||||||
)
|
)
|
||||||
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime)
|
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime, req.ProtoMinor)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
item.ConnectionInfo = &api.ConnectionInfo{
|
item.ConnectionInfo = &api.ConnectionInfo{
|
||||||
ClientIP: tcpID.SrcIP,
|
ClientIP: tcpID.SrcIP,
|
||||||
@ -175,7 +175,7 @@ func handleHTTP1ServerStream(b *bufio.Reader, tcpID *api.TcpID, counterPair *api
|
|||||||
counterPair.Response,
|
counterPair.Response,
|
||||||
"HTTP1",
|
"HTTP1",
|
||||||
)
|
)
|
||||||
item := reqResMatcher.registerResponse(ident, res, superTimer.CaptureTime)
|
item := reqResMatcher.registerResponse(ident, res, superTimer.CaptureTime, res.ProtoMinor)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
item.ConnectionInfo = &api.ConnectionInfo{
|
item.ConnectionInfo = &api.ConnectionInfo{
|
||||||
ClientIP: tcpID.DstIP,
|
ClientIP: tcpID.DstIP,
|
||||||
|
@ -235,8 +235,8 @@ func checkIsHTTP2ServerStream(b *bufio.Reader) (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If response starts with this text, it is HTTP/1.x
|
// If response starts with HTTP/1. then it's not HTTP/2
|
||||||
if bytes.Compare(buf, []byte("HTTP/1.0 ")) == 0 || bytes.Compare(buf, []byte("HTTP/1.1 ")) == 0 {
|
if bytes.HasPrefix(buf, []byte("HTTP/1.")) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,21 @@ import (
|
|||||||
"github.com/up9inc/mizu/tap/api"
|
"github.com/up9inc/mizu/tap/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var protocol api.Protocol = api.Protocol{
|
var http10protocol api.Protocol = api.Protocol{
|
||||||
|
Name: "http",
|
||||||
|
LongName: "Hypertext Transfer Protocol -- HTTP/1.0",
|
||||||
|
Abbreviation: "HTTP",
|
||||||
|
Macro: "http",
|
||||||
|
Version: "1.0",
|
||||||
|
BackgroundColor: "#205cf5",
|
||||||
|
ForegroundColor: "#ffffff",
|
||||||
|
FontSize: 12,
|
||||||
|
ReferenceLink: "https://datatracker.ietf.org/doc/html/rfc1945",
|
||||||
|
Ports: []string{"80", "443", "8080"},
|
||||||
|
Priority: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
var http11protocol api.Protocol = api.Protocol{
|
||||||
Name: "http",
|
Name: "http",
|
||||||
LongName: "Hypertext Transfer Protocol -- HTTP/1.1",
|
LongName: "Hypertext Transfer Protocol -- HTTP/1.1",
|
||||||
Abbreviation: "HTTP",
|
Abbreviation: "HTTP",
|
||||||
@ -69,12 +83,12 @@ func init() {
|
|||||||
type dissecting string
|
type dissecting string
|
||||||
|
|
||||||
func (d dissecting) Register(extension *api.Extension) {
|
func (d dissecting) Register(extension *api.Extension) {
|
||||||
extension.Protocol = &protocol
|
extension.Protocol = &http11protocol
|
||||||
extension.MatcherMap = reqResMatcher.openMessagesMap
|
extension.MatcherMap = reqResMatcher.openMessagesMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d dissecting) Ping() {
|
func (d dissecting) Ping() {
|
||||||
log.Printf("pong %s", protocol.Name)
|
log.Printf("pong %s", http11protocol.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, counterPair *api.CounterPair, superTimer *api.SuperTimer, superIdentifier *api.SuperIdentifier, emitter api.Emitter, options *api.TrafficFilteringOptions) error {
|
func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, counterPair *api.CounterPair, superTimer *api.SuperTimer, superIdentifier *api.SuperIdentifier, emitter api.Emitter, options *api.TrafficFilteringOptions) error {
|
||||||
@ -96,7 +110,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, co
|
|||||||
http2Assembler = createHTTP2Assembler(b)
|
http2Assembler = createHTTP2Assembler(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
if superIdentifier.Protocol != nil && superIdentifier.Protocol != &protocol {
|
if superIdentifier.Protocol != nil && superIdentifier.Protocol != &http11protocol {
|
||||||
return errors.New("Identified by another protocol")
|
return errors.New("Identified by another protocol")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +142,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, co
|
|||||||
tcpID.DstPort,
|
tcpID.DstPort,
|
||||||
"HTTP2",
|
"HTTP2",
|
||||||
)
|
)
|
||||||
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime)
|
item := reqResMatcher.registerRequest(ident, req, superTimer.CaptureTime, req.ProtoMinor)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
item.ConnectionInfo = &api.ConnectionInfo{
|
item.ConnectionInfo = &api.ConnectionInfo{
|
||||||
ClientIP: tcpID.SrcIP,
|
ClientIP: tcpID.SrcIP,
|
||||||
@ -154,7 +168,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, co
|
|||||||
if !dissected {
|
if !dissected {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
superIdentifier.Protocol = &protocol
|
superIdentifier.Protocol = &http11protocol
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,9 +456,9 @@ func (d dissecting) Represent(request map[string]interface{}, response map[strin
|
|||||||
|
|
||||||
func (d dissecting) Macros() map[string]string {
|
func (d dissecting) Macros() map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
`http`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s"`, protocol.Name, protocol.Version),
|
`http`: fmt.Sprintf(`proto.name == "%s" and proto.version.startsWith("%c")`, http11protocol.Name, http11protocol.Version[0]),
|
||||||
`http2`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s"`, protocol.Name, http2Protocol.Version),
|
`http2`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s"`, http11protocol.Name, http2Protocol.Version),
|
||||||
`grpc`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s" and proto.macro == "%s"`, protocol.Name, grpcProtocol.Version, grpcProtocol.Macro),
|
`grpc`: fmt.Sprintf(`proto.name == "%s" and proto.version == "%s" and proto.macro == "%s"`, http11protocol.Name, grpcProtocol.Version, grpcProtocol.Macro),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ func createResponseRequestMatcher() requestResponseMatcher {
|
|||||||
return *newMatcher
|
return *newMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *requestResponseMatcher) registerRequest(ident string, request *http.Request, captureTime time.Time) *api.OutputChannelItem {
|
func (matcher *requestResponseMatcher) registerRequest(ident string, request *http.Request, captureTime time.Time, protoMinor int) *api.OutputChannelItem {
|
||||||
split := splitIdent(ident)
|
split := splitIdent(ident)
|
||||||
key := genKey(split)
|
key := genKey(split)
|
||||||
|
|
||||||
@ -41,14 +41,14 @@ func (matcher *requestResponseMatcher) registerRequest(ident string, request *ht
|
|||||||
if responseHTTPMessage.IsRequest {
|
if responseHTTPMessage.IsRequest {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return matcher.preparePair(&requestHTTPMessage, responseHTTPMessage)
|
return matcher.preparePair(&requestHTTPMessage, responseHTTPMessage, protoMinor)
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher.openMessagesMap.Store(key, &requestHTTPMessage)
|
matcher.openMessagesMap.Store(key, &requestHTTPMessage)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *requestResponseMatcher) registerResponse(ident string, response *http.Response, captureTime time.Time) *api.OutputChannelItem {
|
func (matcher *requestResponseMatcher) registerResponse(ident string, response *http.Response, captureTime time.Time, protoMinor int) *api.OutputChannelItem {
|
||||||
split := splitIdent(ident)
|
split := splitIdent(ident)
|
||||||
key := genKey(split)
|
key := genKey(split)
|
||||||
|
|
||||||
@ -67,14 +67,18 @@ func (matcher *requestResponseMatcher) registerResponse(ident string, response *
|
|||||||
if !requestHTTPMessage.IsRequest {
|
if !requestHTTPMessage.IsRequest {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return matcher.preparePair(requestHTTPMessage, &responseHTTPMessage)
|
return matcher.preparePair(requestHTTPMessage, &responseHTTPMessage, protoMinor)
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher.openMessagesMap.Store(key, &responseHTTPMessage)
|
matcher.openMessagesMap.Store(key, &responseHTTPMessage)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *requestResponseMatcher) preparePair(requestHTTPMessage *api.GenericMessage, responseHTTPMessage *api.GenericMessage) *api.OutputChannelItem {
|
func (matcher *requestResponseMatcher) preparePair(requestHTTPMessage *api.GenericMessage, responseHTTPMessage *api.GenericMessage, protoMinor int) *api.OutputChannelItem {
|
||||||
|
protocol := http11protocol
|
||||||
|
if protoMinor == 0 {
|
||||||
|
protocol = http10protocol
|
||||||
|
}
|
||||||
return &api.OutputChannelItem{
|
return &api.OutputChannelItem{
|
||||||
Protocol: protocol,
|
Protocol: protocol,
|
||||||
Timestamp: requestHTTPMessage.CaptureTime.UnixNano() / int64(time.Millisecond),
|
Timestamp: requestHTTPMessage.CaptureTime.UnixNano() / int64(time.Millisecond),
|
||||||
|
@ -35,7 +35,7 @@ export function getClassification(statusCode: number): string {
|
|||||||
let classification = StatusCodeClassification.NEUTRAL;
|
let classification = StatusCodeClassification.NEUTRAL;
|
||||||
|
|
||||||
// 1 - 16 HTTP/2 (gRPC) status codes
|
// 1 - 16 HTTP/2 (gRPC) status codes
|
||||||
// 2xx - 5xx HTTP/1.1 status codes
|
// 2xx - 5xx HTTP/1.x status codes
|
||||||
if ((statusCode >= 200 && statusCode <= 399) || statusCode === 0) {
|
if ((statusCode >= 200 && statusCode <= 399) || statusCode === 0) {
|
||||||
classification = StatusCodeClassification.SUCCESS;
|
classification = StatusCodeClassification.SUCCESS;
|
||||||
} else if (statusCode >= 400 || (statusCode >= 1 && statusCode <= 16)) {
|
} else if (statusCode >= 400 || (statusCode >= 1 && statusCode <= 16)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user