github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/pkg/ebpftracer/signature/socks5_detected.go (about) 1 package signature 2 3 import ( 4 "fmt" 5 6 v1 "github.com/castai/kvisor/api/v1/runtime" 7 "github.com/castai/kvisor/pkg/ebpftracer/events" 8 "github.com/castai/kvisor/pkg/ebpftracer/types" 9 "github.com/castai/kvisor/pkg/net/packet" 10 "github.com/castai/kvisor/pkg/proc" 11 "github.com/elastic/go-freelru" 12 ) 13 14 var _ Signature = (*SOCKS5Detected)(nil) 15 16 type SOCKS5DetectionState uint8 17 18 const ( 19 SOCKS5Unknown SOCKS5DetectionState = iota 20 SOCKS5InitialClientRequestReceived 21 SOCKS5InitialClientRequestSend 22 SOCKS5InitialServerResponseSend 23 SOCKS5InitialServerResponseReceived 24 ) 25 26 const DefaultSOCKS5SignatureCacheSize = 1024 27 28 type SOCKS5DetectionSignatureConfig struct { 29 CacheSize uint32 30 } 31 32 type SOCKS5Detected struct { 33 detectionStateCache freelru.Cache[proc.PID, SOCKS5DetectionState] 34 } 35 36 func NewSOCKS5DetectedSignature(cfg SOCKS5DetectionSignatureConfig) (Signature, error) { 37 var cacheSize uint32 = DefaultSOCKS5SignatureCacheSize 38 if cfg.CacheSize > 0 { 39 cacheSize = cfg.CacheSize 40 } 41 42 cache, err := freelru.NewSynced[proc.PID, SOCKS5DetectionState](cacheSize, func(u uint32) uint32 { 43 return u 44 }) 45 if err != nil { 46 return nil, err 47 } 48 49 return &SOCKS5Detected{ 50 detectionStateCache: cache, 51 }, nil 52 } 53 54 func (*SOCKS5Detected) GetMetadata() SignatureMetadata { 55 return SignatureMetadata{ 56 ID: v1.SignatureEventID_SIGNATURE_SOCKS5_DETECTED, 57 Name: "socks5_detected", 58 Version: "0.0.1", 59 TargetEvents: []events.ID{ 60 events.NetPacketSOCKS5Base, 61 }, 62 } 63 } 64 65 func toProtocolAddressType(t packet.SOCKS5AddressType) v1.SOCKS5AddressType { 66 switch t { 67 case packet.SOCKS5AddressTypeIPv4: 68 return v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_IPv4 69 case packet.SOCKS5AddressTypeDomainName: 70 return v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_DOMAIN_NAME 71 case packet.SOCKS5AddressTypeIPv6: 72 return v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_IPv6 73 } 74 75 return v1.SOCKS5AddressType_SOCKS5_ADDRESS_TYPE_UNKNOWN 76 } 77 78 func toProtocolFlowDirection(f types.FlowDirection) v1.FlowDirection { 79 switch f { 80 case types.FlowDirectionIngress: 81 return v1.FlowDirection_FLOW_INGRESS 82 case types.FlowDirectionEgress: 83 return v1.FlowDirection_FLOW_EGRESS 84 default: 85 return v1.FlowDirection_FLOW_UNKNOWN 86 } 87 } 88 89 func toSOCKS5Finding(state SOCKS5DetectionState, flowDirection types.FlowDirection, msg packet.SOCKS5RequestOrReply) *v1.SOCKS5DetectedFinding { 90 var role v1.SOCKS5Role 91 92 switch state { 93 case SOCKS5InitialClientRequestSend, SOCKS5InitialServerResponseReceived: 94 role = v1.SOCKS5Role_SOCKS5_ROLE_CLIENT 95 case SOCKS5InitialClientRequestReceived, SOCKS5InitialServerResponseSend: 96 role = v1.SOCKS5Role_SOCKS5_ROLE_SERVER 97 default: 98 role = v1.SOCKS5Role_SOCKS5_ROLE_UNKNOWN 99 } 100 101 return &v1.SOCKS5DetectedFinding{ 102 Role: role, 103 FlowDirection: toProtocolFlowDirection(flowDirection), 104 CmdOrReply: uint32(msg.CmdOrReply), 105 AddressType: toProtocolAddressType(msg.AddressType), 106 Address: msg.Address, 107 Port: uint32(msg.Port), 108 } 109 } 110 111 func (s *SOCKS5Detected) OnEvent(event *types.Event) *v1.SignatureFinding { 112 var networkData []byte 113 114 switch args := event.Args.(type) { 115 case types.NetPacketSOCKS5BaseArgs: 116 networkData = args.Payload 117 default: 118 return nil 119 } 120 121 payload, _, err := packet.ExtractPayload(networkData) 122 if err != nil { 123 fmt.Println(err) 124 return nil 125 } 126 127 message, err := packet.ParseSOCKS5(payload) 128 if err != nil { 129 return nil 130 } 131 132 flowDirection := event.Context.GetFlowDirection() 133 134 switch msg := message.(type) { 135 case packet.SOCKS5InitialClientRequest: 136 switch flowDirection { 137 case types.FlowDirectionEgress: 138 s.detectionStateCache.Add(event.Context.Pid, SOCKS5InitialClientRequestSend) 139 case types.FlowDirectionIngress: 140 s.detectionStateCache.Add(event.Context.Pid, SOCKS5InitialClientRequestReceived) 141 } 142 143 return nil 144 145 case packet.SOCKS5InitialServerResponse: 146 switch flowDirection { 147 case types.FlowDirectionEgress: 148 s.detectionStateCache.Add(event.Context.Pid, SOCKS5InitialServerResponseSend) 149 case types.FlowDirectionIngress: 150 s.detectionStateCache.Add(event.Context.Pid, SOCKS5InitialServerResponseReceived) 151 } 152 153 return nil 154 155 case packet.SOCKS5RequestOrReply: 156 state, found := s.detectionStateCache.Get(event.Context.Pid) 157 if !found { 158 state = SOCKS5Unknown 159 } 160 161 return &v1.SignatureFinding{ 162 Data: &v1.SignatureFinding_Socks5Detected{ 163 Socks5Detected: toSOCKS5Finding(state, flowDirection, msg), 164 }, 165 } 166 } 167 168 return &v1.SignatureFinding{} 169 }