Hôm nay bạn sẽ học cách chặn IP mạng TOR (relay và bridge) bằng Cloudflare Workers hoàn toàn miễn phí.

Trước khi đi vào chi tiết, tôi phải thông báo rằng Cloudflare gần đây đã giới thiệu Managed Lists nơi việc chặn TOR có thể được thực hiện chỉ bằng một cú nhấp chuột. Nhược điểm duy nhất là những tính năng này chỉ dành cho khách hàng Enterprise.

Nếu bạn có đủ khả năng, tuyệt vời; bạn có thể bỏ qua bài viết này. Tuy nhiên nếu bạn không thể mua gói Enterprise, hãy tiếp tục đọc.

Chặn mạng TOR

Ban đầu tôi đã tạo một worker chỉ được sử dụng như một cron job, lấy các IP TOR, phân tích và lưu trữ chúng trong Cloudflare Lists. Danh sách này sau đó sẽ được sử dụng trên bất kỳ trang web nào trong Firewall Rules.

Vấn đề chính với tính năng Lists là nó bị giới hạn 10.000 mục trên tất cả các danh sách. Vì vậy không quan trọng bạn đang dùng gói Business hay Enterprise, đó là giới hạn hiện tại như đã ghi tại đây .

Vấn đề khác là bạn hiện không thể lưu trữ các địa chỉ IPv6 riêng lẻ, như đã nêu tại đây .

Với hai vấn đề lớn này, việc sử dụng danh sách không phải là lựa chọn khả thi; vì vậy tôi đã chuyển sang Workers KV. Sau nhiều thử nghiệm và thảo luận với nhiều người trên kênh Discord của Cloudflare, tôi đã tìm ra cách tốt nhất để lưu trữ các IP TOR này và truy vấn chúng.

Sử dụng cách tiếp cận “thông minh”, tôi chỉ lưu trữ một mục nhập (key:value) cho tất cả các IP TOR; giúp tiết kiệm đáng kể chi phí.

Điều này hoạt động vì giới hạn giá trị của Workers KV là 25 Mb, trong khi nhiều IP chúng ta lưu trữ chỉ chiếm vài Kb.

Giới hạn của gói miễn phí Workers KV là quá đủ để viết/đọc các IP này liên tục. Và trong trường hợp không đủ, có thể áp dụng bộ nhớ đệm trong worker (tôi đã áp dụng bộ nhớ đệm 10 phút cho READ) và gói có thể được nâng cấp chỉ với 5$/tháng.

Tất nhiên bạn cũng có thể sử dụng thông minh và chỉ kiểm tra IP người dùng trong các khu vực cụ thể bạn muốn bảo vệ, ví dụ khu vực Đăng nhập và những nơi khác.

Service worker

Tôi đã chuẩn bị một worker sẵn sàng sử dụng cho bạn trên Github .

Tất cả những gì bạn cần làm là clone nó, cấu hình các yêu cầu và xuất bản.

Cấu hình

Để điều này hoạt động, bạn cần một vài thứ:

  • Wrangler
  • Account ID của bạn
  • Một KV Namespace

Để lấy Account ID, chỉ cần mở bất kỳ trang web nào trên Cloudflare và kiểm tra phía dưới bên phải trang “Overview”. Khi có Account ID, lưu nó trong wrangler.toml:

1account_id = "..."

Để tạo Worker KV Namespace, thực thi lệnh sau:

sudo wrangler kv:namespace create storage

Kết quả sẽ là:

1🌀 Creating namespace with title "cloudflare-block-tor-worker-storage"
2✨ Success!
3Add the following to your configuration file:
4kv_namespaces = [
5{ binding = "storage", id = "cc309bd612d9476f8abdc43ec4f93fd6" }
6]

Sử dụng ID ở trên, chỉnh sửa wrangler.toml và lưu ID:

1[[kv_namespaces]]
2binding = "TOR_COMBINED_LIST"
3id = "cc309bd612d9476f8abdc43ec4f93fd6"

Vui lòng không tự tạo KV Namespace, hãy sử dụng lệnh ở trên. KV Binding là bắt buộc, đừng bỏ qua nó.

Khi các bước trên hoàn tất, xuất bản worker:

sudo wrangler publish

Worker được cấu hình để chạy mỗi 60 phút (một giờ), nếu bạn muốn thay đổi chỉ cần chỉnh sửa wrangler.toml. Khoảng thời gian ngắn hơn sẽ không giúp ích vì API chỉ cập nhật mỗi giờ.

Sử dụng danh sách

Bây giờ bạn có danh sách IP mạng TOR và đã đến lúc sử dụng. Điều này cực kỳ đơn giản nếu bạn đã quen thuộc với workers, và nếu chưa thì vẫn dễ dàng.

Ý tưởng là kiểm tra IP người dùng đến so với danh sách và nếu có khớp, chặn yêu cầu. Dưới đây là một script khởi đầu đơn giản mà bạn có thể copy và paste vào một worker mới:

 1const clientIP = request.headers.get('CF-Connecting-IP');
 2const ipset = await TOR_COMBINED_LIST.get("ipset", { type: "json", cacheTtl: 600 });
 3
 4if (ipset[clientIP])
 5{
 6return new Response("TOR is Forbidden", {
 7headers: {
 8'content-type': 'text/html;charset=UTF-8',
 9},
10status: 403
11});
12}

Việc tra cứu cực kỳ nhanh vì danh sách IP được lưu trữ dưới dạng một đối tượng, nên bạn không cần phân tích hay tìm kiếm gì.

Bộ nhớ đệm cũng được áp dụng (bạn có thể tắt nếu muốn) để tăng tốc hơn nữa. Bộ nhớ đệm Workers KV hoạt động bằng cách sử dụng Cache API .

Sau khi lấy giá trị, bạn chỉ cần kiểm tra xem IP có tồn tại không, nếu có thì trả về bất cứ thứ gì bạn muốn.

Sử dụng đoạn mã trên ở bất kỳ đâu trong worker mới hoặc hiện có (và cả Cloudflare Pages), miễn là đối tượng request có sẵn.

Kiểm thử danh sách

Như đã đề cập trước đó, việc sử dụng danh sách này cực kỳ dễ dàng ngay cả khi bạn chưa bao giờ sử dụng Workers.

Tôi đã tạo một ví dụ nhỏ mà bạn có thể đơn giản copy paste và sử dụng trên bất kỳ trang web nào:

 1addEventListener("fetch", event => {
 2event.respondWith(handleRequest(event.request))
 3})
 4
 5const html = `<!doctype html>
 6
 7<html lang="en">
 8  <head>
 9    <title>Access Denied</title>
10    <meta charset="utf-8">
11    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
12    <meta name="robots" content="noindex, nofollow" />
13    <meta name="viewport" content="width=device-width, initial-scale=1">
14    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> 
15  </head>
16  <body>
17    <div class="container">
18      <h1 class="mt-5 text-center">Oops!</h1>
19      <h2 class="mt-2 text-center text-danger">TOR Network is not allowed.</h2>
20    </div>
21  </body>
22</html>`;
23
24async function handleRequest(request)
25{
26const clientIP = request.headers.get('CF-Connecting-IP');
27const ipset = await TOR_COMBINED_LIST.get("ipset", { type: "json", cacheTtl: 600 });
28
29if (ipset[clientIP])
30{
31return new Response(html, {
32headers: {
33'content-type': 'text/html;charset=UTF-8',
34},
35status: 403
36});
37}
38
39const response = await fetch(request);
40
41return response;
42}

Đừng quên thêm KV Binding vào worker này.

Với worker trên đã triển khai, chúng ta khởi động Trình duyệt TOR và kiểm thử:

Block TOR Result

Như bạn có thể thấy, nó hoạt động chính xác như mong đợi. IP mạng TOR đã bị chặn, cả relay và bridge.

Xin lưu ý rằng tôi đã gỡ bỏ tính năng này khỏi trang web của mình, vì vậy nếu bạn thử truy cập qua TOR bây giờ thì nó sẽ hoạt động (tôi không có lý do để chặn TOR).

Tính toán chi phí

Ngay từ đầu bài viết tôi đã đề cập rằng giới hạn Worker miễn phí đủ để chặn TOR, và đúng là vậy. Tôi cũng đề cập rằng đã thực hiện nhiều thử nghiệm để tìm ra cách tốt nhất tạo dự án này.

Trong quá trình thử nghiệm, tôi đã sử dụng nhiều yêu cầu READ/WRITE/LIST/DELETE mà cuối cùng tốn khoảng 60-100$ mỗi tháng. Không lý tưởng phải không? 😳

Vì vậy tôi đã tìm ra cách chỉ thực hiện một WRITE mỗi giờ. Điều đó có nghĩa là 24 WRITE mỗi ngày, 744 WRITE mỗi tháng (31 ngày).

Điều này nằm trong gói miễn phí của Workers KV và bạn có thể chặn TOR.

Liên kết hữu ích

Vậy đấy, tôi hy vọng bài viết và công cụ này đã giúp ích cho bạn.

Hãy cho tôi biết suy nghĩ của bạn!