github.com/chainreactors/fingers@v1.2.1/fingers/nacos_fingerprint_test.go (about) 1 package fingers 2 3 import ( 4 "crypto/tls" 5 "net/http" 6 "testing" 7 "time" 8 9 "github.com/chainreactors/utils/encode" 10 "github.com/chainreactors/utils/httputils" 11 "gopkg.in/yaml.v3" 12 ) 13 14 func TestNacosFingerprint_RealSite(t *testing.T) { 15 if testing.Short() { 16 t.Skip("skipping live network test in short mode") 17 } 18 const ( 19 baseURL = "https://nacos.lzfzkj.com" 20 fingerSendPath = "/nacos/" 21 faviconSendPath = "/nacos/console-ui/public/img/nacos-logo.png" 22 expectedMMH3 = "13942501" 23 ) 24 25 finger := &Finger{ 26 Name: "nacos", 27 Focus: true, 28 Tags: []string{"nacos"}, 29 Protocol: HTTPProtocol, 30 DefaultPort: []string{"80"}, 31 SendDataStr: fingerSendPath, 32 EnableMatchDetail: true, 33 Rules: Rules{ 34 { 35 Regexps: &Regexps{ 36 Body: []string{"<title>Nacos</title>"}, 37 }, 38 }, 39 { 40 Favicon: &Favicons{ 41 Mmh3: []string{expectedMMH3}, 42 }, 43 SendDataStr: faviconSendPath, 44 Level: 2, 45 }, 46 }, 47 } 48 49 if err := finger.Compile(false); err != nil { 50 t.Fatalf("failed to compile finger: %v", err) 51 } 52 53 client := &http.Client{ 54 Timeout: 20 * time.Second, 55 Transport: &http.Transport{ 56 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 57 }, 58 } 59 60 sent := make([]string, 0, 4) 61 sender := Sender(func(data []byte) ([]byte, bool) { 62 path := string(data) 63 sent = append(sent, path) 64 req, err := http.NewRequest(http.MethodGet, baseURL+path, nil) 65 if err != nil { 66 t.Logf("request build error for %s: %v", path, err) 67 return nil, false 68 } 69 req.Header.Set("User-Agent", "fingers-test/nacos-fingerprint") 70 resp, err := client.Do(req) 71 if err != nil { 72 t.Logf("request error for %s: %v", path, err) 73 return nil, false 74 } 75 defer resp.Body.Close() 76 return httputils.ReadRaw(resp), true 77 }) 78 79 frame, _, ok := finger.ActiveMatch(2, sender) 80 if !ok || frame == nil { 81 t.Fatalf("expected nacos active match to succeed") 82 } 83 84 // Validate the favicon hash from the real site. 85 req, err := http.NewRequest(http.MethodGet, baseURL+faviconSendPath, nil) 86 if err != nil { 87 t.Fatalf("failed to build favicon request: %v", err) 88 } 89 resp, err := client.Do(req) 90 if err != nil { 91 t.Skipf("network error fetching favicon path: %v", err) 92 return 93 } 94 defer resp.Body.Close() 95 raw := httputils.ReadRaw(resp) 96 body, _, splitOK := httputils.SplitHttpRaw(raw) 97 if !splitOK || len(body) == 0 { 98 t.Fatalf("failed to split favicon response body") 99 } 100 if got := encode.Mmh3Hash32(body); got != expectedMMH3 { 101 t.Fatalf("unexpected mmh3 for favicon: got %s want %s", got, expectedMMH3) 102 } 103 104 t.Logf("sent paths: %v", sent) 105 if frame.MatchDetail != nil { 106 t.Logf("matcher detail: %+v", *frame.MatchDetail) 107 } 108 } 109 110 func TestNacosFingerprint_RealSite_RuleSendDataOnly(t *testing.T) { 111 if testing.Short() { 112 t.Skip("skipping live network test in short mode") 113 } 114 const ( 115 baseURL = "https://nacos.lzfzkj.com" 116 faviconSendPath = "/nacos/console-ui/public/img/nacos-logo.png" 117 expectedMMH3 = "13942501" 118 ) 119 120 yamlContent := `name: nacos 121 focus: true 122 tag: 123 - nacos 124 rule: 125 - regexps: 126 body: 127 - <title>Nacos</title> 128 - favicon: 129 mmh3: 130 - "` + expectedMMH3 + `" 131 send_data: ` + faviconSendPath + ` 132 ` 133 134 var parsed Fingers 135 if err := yaml.Unmarshal([]byte(yamlContent), &parsed); err != nil { 136 var single Finger 137 if errSingle := yaml.Unmarshal([]byte(yamlContent), &single); errSingle != nil { 138 t.Fatalf("failed to parse yaml: %v", err) 139 } 140 parsed = Fingers{&single} 141 } 142 if len(parsed) == 0 || parsed[0] == nil { 143 t.Fatalf("no fingerprint parsed from yaml") 144 } 145 finger := parsed[0] 146 finger.EnableMatchDetail = true 147 if err := finger.Compile(false); err != nil { 148 t.Fatalf("failed to compile finger: %v", err) 149 } 150 151 client := &http.Client{ 152 Timeout: 20 * time.Second, 153 Transport: &http.Transport{ 154 TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 155 }, 156 } 157 158 sent := make([]string, 0, 4) 159 sender := Sender(func(data []byte) ([]byte, bool) { 160 path := string(data) 161 sent = append(sent, path) 162 req, err := http.NewRequest(http.MethodGet, baseURL+path, nil) 163 if err != nil { 164 t.Logf("request build error for %s: %v", path, err) 165 return nil, false 166 } 167 req.Header.Set("User-Agent", "fingers-test/nacos-fingerprint") 168 resp, err := client.Do(req) 169 if err != nil { 170 t.Logf("request error for %s: %v", path, err) 171 return nil, false 172 } 173 defer resp.Body.Close() 174 return httputils.ReadRaw(resp), true 175 }) 176 177 frame, _, ok := finger.ActiveMatch(2, sender) 178 if !ok || frame == nil { 179 t.Fatalf("expected nacos active match to succeed") 180 } 181 182 if len(sent) == 0 { 183 t.Fatalf("expected at least one send_data to be sent") 184 } 185 186 t.Logf("sent paths: %v", sent) 187 if frame.MatchDetail != nil { 188 t.Logf("matcher detail: %+v", *frame.MatchDetail) 189 } 190 }