CAPSOLVER
Blog
Cách giải quyết dấu vân tay TLS trong n8n với CapSolver

Cách giải quyết tính năng nhận dạng TLS trong n8n với CapSolver

Logo of CapSolver

Anh Tuan

Data Science Expert

18-Mar-2026

Nếu bạn từng cố gắng quét một trang web được bảo vệ bởi hệ thống phát hiện bot cấp doanh nghiệp, bạn có thể đã gặp phải một bức tường vô hình: các yêu cầu của bạn bị chặn ngay cả khi header, cookie và User-Agent của bạn hoàn hảo. Lý do? Bắt chước TLS - và điều này xảy ra trước khi yêu cầu HTTP được gửi đi.

Các dịch vụ chống bot như Cloudflare, Akamai, DataDome và các dịch vụ khác kiểm tra cuộc trao đổi TLS thô để xác định xem client có phải là trình duyệt thực sự hay không hay là công cụ tự động hóa. Các client HTTP tiêu chuẩn - Go's net/http, Python's requests, curl, Node.js axios - tất cả đều có các dấu vân tay TLS riêng biệt bị phát hiện ngay lập tức.

Trong hướng dẫn này, bạn sẽ xây dựng một máy chủ Go nhẹ sử dụng httpcloak để giả mạo dấu vân tay TLS của Chrome thực sự, và kết nối nó với các quy trình n8n của bạn để mọi yêu cầu HTTP trông giống như lưu lượng truy cập trình duyệt Chrome thật sự ở cấp độ mạng.


Bắt chước TLS là gì?

Mỗi lần client kết nối với một trang web qua HTTPS, nó khởi tạo một cuộc trao đổi TLS bằng cách gửi một thông điệp ClientHello. Thông điệp này chứa:

  • Các bộ giao thức mã hóa - các thuật toán mã hóa mà client hỗ trợ, và thứ tự của chúng
  • Mở rộng TLS - các tính năng như SNI, ALPN, các nhóm được hỗ trợ, thuật toán chữ ký
  • Các đường cong elliptic và định dạng điểm - các tham số mật mã học
  • Phiên bản TLS - phiên bản TLS tối đa mà client hỗ trợ

Các dịch vụ chống bot trích xuất các giá trị này và tính toán một dấu vân tay - gọi là dấu vân tay JA3 hoặc JA4 - mà xác định duy nhất phần mềm client. Mỗi trình duyệt, thư viện HTTP và môi trường chạy ngôn ngữ lập trình đều tạo ra một dấu vân tay khác nhau.

Client Dấu vân tay JA3 Được phát hiện là
Chrome 145 Mã băm duy nhất khớp với trình duyệt Chrome Trình duyệt thực sự
Firefox 130 Mã băm khác - Firefox sử dụng các ưu tiên giao thức khác Trình duyệt thực sự
Go net/http Mã băm hoàn toàn khác - stack TLS của Go dễ nhận biết Bot / công cụ tự động hóa
Python requests Mã băm khác biệt - TLS của urllib3 của Python dễ nhận biết Bot / công cụ tự động hóa
curl Mã băm khác - dấu vân tay TLS của curl đã được biết đến Bot / công cụ tự động hóa
Node.js axios Dấu vân tay TLS của Node.js - dễ bị phát hiện Bot / công cụ tự động hóa

Bài học chính: Bắt chước TLS xảy ra trong quá trình trao đổi, trước khi bất kỳ header HTTP nào được gửi đi. Không có cách nào để sửa chữa dấu vân tay TLS không phải trình duyệt bằng cách điều chỉnh header.


Tại sao các client HTTP tiêu chuẩn thất bại

Khi trình duyệt kết nối với một trang web qua HTTPS, nó gửi một thông điệp ClientHello TLS bao gồm các chi tiết về các bộ giao thức, mở rộng và cài đặt được hỗ trợ. Các dịch vụ chống bot ghi lại dấu vân tay này (gọi là dấu vân tay JA3/JA4) và so sánh với các hồ sơ trình duyệt đã biết.

net/http của Go, requests của Python, curl và hầu hết các thư viện HTTP đều có dấu vân tay TLS riêng biệt. Ngay cả khi cookie và header đúng, các hệ thống chống bot sẽ chặn yêu cầu nếu chúng phát hiện dấu vân tay TLS không phải trình duyệt.

Dưới đây là các bước xảy ra:

  1. Quy trình n8n của bạn gửi một yêu cầu HTTP đến trang web được bảo vệ
  2. Cuộc trao đổi TLS bắt đầu - client của bạn gửi ClientHello của nó
  3. Dịch vụ chống bot ghi lại dấu vân tay JA3/JA4 từ cuộc trao đổi
  4. Dấu vân tay khớp với Go/Python/Node.js - không phải Chrome hoặc Firefox
  5. Yêu cầu bị chặn, bị yêu cầu xác minh hoặc được phục vụ một trang giả - trước khi header của bạn được đánh giá

Đây là lý do tại sao việc đặt User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... không giúp gì. User-Agent là một header cấp HTTP. Bắt chước TLS hoạt động ở cấp độ thấp hơn. Nếu User-Agent của bạn nói Chrome nhưng dấu vân tay TLS của bạn nói Go, yêu cầu sẽ bị phát hiện ngay lập tức.


Ai sử dụng Bắt chước TLS?

Bắt chước TLS đã trở thành thực hành tiêu chuẩn trong bảo vệ bot doanh nghiệp. Dưới đây là các dịch vụ chính kiểm tra dấu vân tay TLS:

Dịch vụ chống bot Kiểm tra TLS Ghi chú
Cloudflare Bot Management Thách thức "Verifying your browser..." toàn trang. Kiểm tra JA3/JA4 trên mỗi yêu cầu
Akamai Bot Manager Sử dụng bắt chước TLS như một trong nhiều tín hiệu trong điểm bot
DataDome Phân tích dấu vân tay TLS cùng với các tín hiệu hành vi
Nhiều dịch vụ khác Thay đổi Bắt chước TLS đang trở thành tiêu chuẩn trong bảo vệ bot doanh nghiệp

CapSolver hỗ trợ giải quyết các thách thức từ nhiều dịch vụ này. Máy chủ TLS trong hướng dẫn này được thiết kế để hoạt động cùng với bất kỳ quy trình giải captcha nào mà yêu cầu HTTP cuối cùng cần trông giống như trình duyệt thực sự - dù bạn đang vượt qua Cloudflare Challenge, Akamai, DataDome hay bất kỳ hệ thống chống bot nào khác.


Yêu cầu cần thiết

Yêu cầu Ghi chú
n8n tự host Bắt buộc - máy chủ TLS phải chạy trên cùng máy với n8n. n8n Cloud không phù hợp.
Go 1.21+ Phải được cài đặt trên máy chủ. Kiểm tra bằng go version.
Quản lý tiến trình (đề xuất) Bất kỳ quản lý tiến trình nào (systemd, supervisor, Docker, PM2) để giữ cho máy chủ TLS chạy sau khi khởi động lại

Bước 1 - Xây dựng Máy chủ TLS

Máy chủ TLS là một máy chủ HTTP Go nhẹ, nhận yêu cầu trên cổng 7878 và chuyển tiếp chúng bằng cài đặt TLS Chrome-145 của httpcloak.

Tạo tệp nguồn

bash Copy
mkdir -p ~/tls-server && cd ~/tls-server

Tạo một tệp có tên main.go với nội dung sau:

go Copy
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/sardanioss/httpcloak/client"
)

type FetchRequest struct {
	URL     string            `json:"url"`
	Method  string            `json:"method"`
	Headers map[string]string `json:"headers"`
	Proxy   string            `json:"proxy"`
	Body    string            `json:"body"`
}

type FetchResponse struct {
	Status  int                 `json:"status"`
	Body    string              `json:"body"`
	Headers map[string][]string `json:"headers"`
}

type ErrorResponse struct {
	Error string `json:"error"`
}

func writeError(w http.ResponseWriter, status int, msg string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	json.NewEncoder(w).Encode(ErrorResponse{Error: msg})
}

func fetchHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		writeError(w, http.StatusMethodNotAllowed, "only POST allowed")
		return
	}

	var req FetchRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON: "+err.Error())
		return
	}

	if req.URL == "" {
		writeError(w, http.StatusBadRequest, "url is required")
		return
	}
	if req.Method == "" {
		req.Method = "GET"
	}

	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()

	c := client.NewClient("chrome-145", client.WithTimeout(60*time.Second))
	defer c.Close()

	if req.Proxy != "" {
		c.SetProxy(req.Proxy)
	}

	headers := make(map[string][]string, len(req.Headers))
	var userAgent string
	for k, v := range req.Headers {
		lower := strings.ToLower(k)
		if lower == "user-agent" {
			userAgent = v
		} else {
			headers[k] = []string{v}
		}
	}

	var bodyReader io.Reader
	if req.Body != "" {
		bodyReader = strings.NewReader(req.Body)
	}

	hcReq := &client.Request{
		Method:    strings.ToUpper(req.Method),
		URL:       req.URL,
		Headers:   headers,
		Body:      bodyReader,
		UserAgent: userAgent,
		FetchMode: client.FetchModeNavigate,
	}

	resp, err := c.Do(ctx, hcReq)
	if err != nil {
		writeError(w, http.StatusBadGateway, "fetch failed: "+err.Error())
		return
	}

	body, err := resp.Text()
	if err != nil {
		writeError(w, http.StatusInternalServerError, "read body failed: "+err.Error())
		return
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(FetchResponse{
		Status:  resp.StatusCode,
		Body:    body,
		Headers: resp.Headers,
	})
}

func main() {
	const port = "7878"

	mux := http.NewServeMux()
	mux.HandleFunc("/fetch", fetchHandler)
	mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		fmt.Fprint(w, `{"status":"ok"}`)
	})

	log.Printf("TLS server (httpcloak chrome-145) listening on :%s", port)
	log.Fatal(http.ListenAndServe(":"+port, mux))
}

Khởi tạo và xây dựng

bash Copy
go mod init tls-server
go get github.com/sardanioss/httpcloak/client
go build -o main main.go

Chạy máy chủ

bash Copy
./main

Máy chủ chạy ở chế độ nền. Để giữ cho nó chạy trong nền, sử dụng bất kỳ quản lý tiến trình nào (systemd, supervisor, Docker, v.v.) hoặc chạy nó trong phiên screen/tmux.

Kiểm tra xem nó có chạy không (trong terminal mới)

bash Copy
curl http://localhost:7878/health

Kết quả mong muốn: {"status":"ok"}

Lưu ý: Máy chủ TLS phải chạy trên máy chủ cùng với phiên bản n8n của bạn. Quy trình n8n gọi nó tại http://localhost:7878/fetch.


Bước 2 - Cho phép n8n gọi localhost

Mặc định, n8n chặn các nút Yêu cầu HTTP từ gọi địa chỉ localhost (bảo vệ SSRF). Bạn cần tắt tính năng này để các quy trình của bạn có thể truy cập máy chủ TLS trên localhost:7878.

Thêm biến môi trường N8N_BLOCK_ACCESS_TO_LOCALHOST=false và khởi động lại n8n của bạn. Cách bạn làm điều này phụ thuộc vào cách bạn chạy n8n:

Nếu bạn chạy n8n trực tiếp:

bash Copy
export N8N_BLOCK_ACCESS_TO_LOCALHOST=false
n8n start

Nếu bạn sử dụng Docker:

Thêm -e N8N_BLOCK_ACCESS_TO_LOCALHOST=false vào lệnh docker run của bạn, hoặc thêm nó vào phần environment trong docker-compose.yml.


Bước 3 - Sử dụng Máy chủ TLS từ n8n

Máy chủ TLS cung cấp một điểm cuối duy nhất chấp nhận bất kỳ yêu cầu HTTP nào và chuyển tiếp nó với dấu vân tay TLS Chrome.

Tham chiếu API

Điểm cuối: POST http://localhost:7878/fetch

Nội dung yêu cầu (JSON):

json Copy
{
  "url": "https://example.com",
  "method": "GET",
  "headers": {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
    "cookie": "cf_clearance=abc123; session=xyz"
  },
  "proxy": "http://user:pass@host:port",
  "body": ""
}
Trường Kiểu Bắt buộc Mô tả
url chuỗi URL đích để truy xuất
method chuỗi Không Phương thức HTTP - mặc định là GET
headers đối tượng Không Các cặp khóa-giá trị của header HTTP để gửi
proxy chuỗi Không URL proxy theo định dạng http://user:pass@host:port
body chuỗi Không Nội dung yêu cầu (đối với yêu cầu POST/PUT)

Phản hồi (JSON):

json Copy
{
  "status": 200,
  "body": "<html>...</html>",
  "headers": { "content-type": ["text/html"], "..." : ["..."] }
}

Cấu hình nút Yêu cầu HTTP trong n8n

Để gọi máy chủ TLS từ quy trình n8n, sử dụng nút Yêu cầu HTTP với các cài đặt sau:

Tham số Giá trị Mô tả
Phương thức POST Luôn POST đến máy chủ TLS
URL http://localhost:7878/fetch Điểm cuối máy chủ TLS cục bộ
Loại nội dung Raw Không sử dụng JSON - chế độ JSON của n8n serial hóa sai
Loại nội dung thô application/json Thông báo cho máy chủ TLS rằng nội dung là JSON
Nội dung ={{ JSON.stringify({ url: "...", method: "GET", headers: {...}, proxy: "..." }) }} Yêu cầu thực tế để chuyển tiếp

Quan trọng: Sử dụng contentType: "json" với JSON.stringify() trong nội dung khiến n8n serial hóa kép, gửi {"": ""} thay vì dữ liệu của bạn. Luôn sử dụng contentType: "raw" với rawContentType: "application/json".

Ví dụ: Truy xuất trang được bảo vệ

Trong biểu thức nội dung nút Yêu cầu HTTP:

javascript Copy
={{ JSON.stringify({
  url: "https://protected-site.com/data",
  method: "GET",
  headers: {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "accept-language": "en-US,en;q=0.9"
  },
  proxy: "http://user:pass@proxy-host:8080"
}) }}

Máy chủ TLS sẽ chuyển tiếp yêu cầu này với dấu vân tay TLS Chrome-145, và trang đích sẽ nhận thấy kết nối trình duyệt Chrome thực sự.


Kiểm tra

Kiểm tra máy chủ TLS trực tiếp từ dòng lệnh:

bash Copy
curl -X POST http://localhost:7878/fetch \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://tls-check.example.com",
    "method": "GET",
    "headers": {
      "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36"
    }
  }'

Bạn có thể xác minh dấu vân tay TLS bằng cách hướng máy chủ đến trình kiểm tra JA3/JA4 - kết quả nên khớp với trình duyệt Chrome thực sự, không phải client thư viện Go.
"contentType": "thô",
"rawContentType": "application/json",
"body": "={{ JSON.stringify(json.body) }}", "options": { "timeout": 60000 } }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.3, "position": [ 100, 0 ], "id": "tls00001-0001-0001-0001-000000000002", "name": "Lấy dữ liệu qua máy chủ TLS" }, { "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify(json) }}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
400,
0
],
"id": "tls00001-0001-0001-0001-000000000003",
"name": "Trả lời webhook"
}
],
"connections": {
"Nhận yêu cầu Solver": {
"main": [
[
{
"node": "Lấy dữ liệu qua máy chủ TLS",
"type": "main",
"index": 0
}
]
]
},
"Lấy dữ liệu qua máy chủ TLS": {
"main": [
[
{
"node": "Trả lời webhook",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
}
}
``


Kết luận

Bạn đã thiết lập một máy chủ giả mạo dấu vân tay TLS khiến các yêu cầu HTTP của n8n trông giống như lưu lượng truy cập trình duyệt Chrome thật sự ở cấp độ mạng. Điều này rất quan trọng để vượt qua các dịch vụ chống bot kiểm tra dấu vân tay TLS.

Máy chủ TLS này hữu ích để vượt qua:

  • Cloudflare Bot Management — các bài kiểm tra toàn trang kiểm tra dấu vân tay TLS
  • Akamai Bot Manager — phát hiện bot doanh nghiệp bằng phân tích TLS
  • DataDome — phân tích hành vi + dấu vân tay TLS
  • PerimeterX / HUMAN — xác thực thiết bị + dấu vân tay TLS
  • Nhiều dịch vụ chống bot khác mà CapSolver hỗ trợ

Thư viện httpcloak với cài đặt Chrome-145 của nó xử lý giả mạo dấu vân tay JA3/JA4, khung SETTINGS HTTP/2, đàm phán ALPN và thứ tự tiêu đề — khiến các yêu cầu của bạn không thể phân biệt được với trình duyệt Chrome thực tế ở cấp độ TLS.


Cần giải CAPTCHA đồng thời với việc giả mạo TLS? Hãy kiểm tra CapSolver — nó tích hợp trực tiếp với n8n như một nút chính thức và hỗ trợ Cloudflare Challenge, Turnstile, reCAPTCHA và nhiều loại khác. Sử dụng mã khuyến mãi n8n để nhận thêm 8% khuyến mãi cho lần nạp tiền đầu tiên!

Banner mã khuyến mãi CapSolver

Câu hỏi thường gặp

Dấu vân tay TLS là gì?

Dấu vân tay TLS là kỹ thuật mà các máy chủ phân tích các đặc điểm của tin nhắn ClientHello TLS của bạn — bao gồm các suite mã hóa, phần mở rộng và thứ tự của chúng — để xác định phần mềm nào đang thực hiện kết nối. Mỗi trình khách HTTP (Chrome, Firefox, curl, Go, Python) có mẫu dấu vân tay duy nhất.

Tại sao tôi không thể chỉ đặt tiêu đề User-Agent thành Chrome?

Tiêu đề User-Agent là thuộc tính ở cấp độ HTTP. Phân tích dấu vân tay TLS xảy ra ở cấp độ thấp hơn — trong quá trình thiết lập TLS, trước khi bất kỳ tiêu đề HTTP nào được gửi. Các dịch vụ chống bot so sánh cả hai lớp: nếu User-Agent của bạn nói Chrome nhưng dấu vân tay TLS của bạn nói Go/Python, yêu cầu sẽ bị đánh dấu là bot.

httpcloak là gì?

httpcloak là thư viện Go giả mạo các hồ sơ TLS thực tế. Nó xử lý khớp dấu vân tay JA3/JA4, khung SETTINGS HTTP/2, đàm phán ALPN và thứ tự tiêu đề. Cài đặt chrome-145 khiến kết nối không thể phân biệt được với trình duyệt Chrome 145 thực tế.

Tôi có thể sử dụng cài đặt phiên bản Chrome khác không?

Có. httpcloak hỗ trợ nhiều cài đặt trình duyệt. Xem tài liệu httpcloak để xem các cài đặt có sẵn. Để thay đổi cài đặt, chỉnh sửa client.NewClient("chrome-145", ...) trong main.go thành hồ sơ trình duyệt mong muốn của bạn.

Chức năng này hoạt động với n8n Cloud không?

Không dễ dàng. Máy chủ TLS là nhị phân Go cục bộ phải chạy trên cùng máy tính với n8n để các quy trình có thể gọi http://localhost:7878/fetch. n8n Cloud không cho phép chạy các dịch vụ cục bộ cùng với các quy trình. Bạn cần phiên bản n8n tự lưu trữ.

Tôi có thể chạy máy chủ TLS trên máy khác không?

Có, nhưng bạn sẽ cần cập nhật URL trong các nút Yêu cầu HTTP của n8n từ http://localhost:7878/fetch thành http://địa chỉ_ip_máy_chủ:7878/fetch, và đảm bảo cổng 7878 có thể truy cập được. Bạn cũng sẽ cần vô hiệu hóa bảo vệ SSRF của n8n hoặc cho phép địa chỉ IP của máy chủ.

Làm thế nào để cập nhật cài đặt Chrome khi có phiên bản mới?

Cập nhật phụ thuộc httpcloak: go get -u github.com/sardanioss/httpcloak/client, thay đổi chuỗi cài đặt trong main.go thành phiên bản mới, xây dựng lại bằng go build -o main main.go, và khởi động lại máy chủ.

Máy chủ TLS có hỗ trợ các yêu cầu đồng thời không?

Có. Máy chủ HTTP của Go xử lý các yêu cầu đồng thời natively. Mỗi yêu cầu tạo ra một phiên bản client httpcloak mới với kết nối TLS riêng. Đối với khối lượng công việc cao, hãy theo dõi sử dụng bộ nhớ vì mỗi kết nối duy trì trạng thái TLS riêng.

Chi phí hiệu năng là bao nhiêu?

Máy chủ TLS thêm độ trễ tối thiểu — thường là 10-50ms cho bước trung gian cục bộ. Phần lớn thời gian yêu cầu được dành cho kết nối HTTPS thực tế đến mục tiêu. Thủ tục thiết lập TLS của Chrome nặng hơn một chút so với mặc định của Go, nhưng điều này không đáng kể trong thực tế.

Làm thế nào để giữ cho máy chủ TLS chạy sau khi khởi động lại máy chủ?

Sử dụng bất kỳ trình quản lý quy trình nào — systemd, supervisor, Docker, hoặc tương tự — để đăng ký máy chủ TLS như một dịch vụ khởi động cùng hệ thống. Đối với cài đặt nhanh, bạn cũng có thể chạy nó bên trong phiên làm việc screen hoặc tmux.

Tuyên bố Tuân thủ: Thông tin được cung cấp trên blog này chỉ mang tính chất tham khảo. CapSolver cam kết tuân thủ tất cả các luật và quy định hiện hành. Việc sử dụng mạng lưới CapSolver cho các hoạt động bất hợp pháp, gian lận hoặc lạm dụng là hoàn toàn bị cấm và sẽ bị điều tra. Các giải pháp giải captcha của chúng tôi nâng cao trải nghiệm người dùng trong khi đảm bảo tuân thủ 100% trong việc giúp giải quyết các khó khăn về captcha trong quá trình thu thập dữ liệu công khai. Chúng tôi khuyến khích việc sử dụng dịch vụ của chúng tôi một cách có trách nhiệm. Để biết thêm thông tin, vui lòng truy cập Điều khoản Dịch vụ và Chính sách Quyền riêng tư.

Thêm