2008-10-02 58 views
12

Đối với ứng dụng máy chủ của tôi, tôi cần kiểm tra xem địa chỉ ip có trong danh sách cấm của chúng tôi hay không.Bạn so sánh địa chỉ IP như thế nào?

Cách hiệu quả nhất để so sánh địa chỉ IP là gì? Sẽ chuyển đổi địa chỉ IP thành số nguyên và so sánh chúng hiệu quả?

+1

là danh sách đen của bạn một tệp, được nạp vào bộ nhớ, trong cơ sở dữ liệu, cái gì? –

+1

Việc đặt danh sách đen ở đâu không quan trọng. Nó vẫn sẽ được so sánh bởi CPU. Nhưng nếu bạn nghĩ rằng tôi nên đề cập đến điều này trong câu hỏi của tôi, xin vui lòng khai sáng cho tôi về lý do tại sao vị trí của danh sách đen là quan trọng. – MrValdez

+1

@MrValdez: Thời gian lấy danh sách đen từ đĩa sẽ vượt quá thời gian để chuyển đổi tất cả các mục nhập của nó từ int thành chuỗi hoặc ngược lại. – MSalters

Trả lời

27

Phụ thuộc vào ngôn ngữ bạn đang sử dụng, nhưng địa chỉ IP thường được lưu trữ dưới dạng số nguyên không dấu 32 bit, ít nhất ở lớp mạng, so sánh khá nhanh. Thậm chí nếu không, trừ khi bạn đang thiết kế một ứng dụng chuyển mạch gói hiệu suất cao, nó không có khả năng là một nút cổ chai hiệu năng. Tránh tối ưu hóa sớm - thiết kế chương trình của bạn cho khả năng thử nghiệm và khả năng mở rộng và nếu bạn có vấn đề về hiệu suất thì bạn có thể sử dụng một trình hồ sơ để xem nơi các nút cổ chai là.

Chỉnh sửa: để làm rõ, địa chỉ IPv4 được lưu dưới dạng số nguyên 32 bit, cộng với mặt nạ mạng (không cần thiết cho so sánh địa chỉ IP). Nếu bạn đang sử dụng IPv6 mới hơn và hiện tại hiếm hơn, thì địa chỉ sẽ dài 128 bit.

+0

"Hiện tại hiếm hơn" có lẽ cần cập nhật 9.5 năm sau? – MichaelChirico

4

Có, tôi đã thấy rằng để có hiệu quả, nó sẽ là một mặc dù dài, và tất nhiên bạn phải lập chỉ mục IP danh sách đen trong dạng nguyên.

7

Các số nguyên 32 bit là cách để đi - cho đến khi bạn bắt đầu xử lý các địa chỉ IPv6 128 bit.

3

Sử dụng công cụ như PeerGuardian không cho phép các kết nối TCP/IP đến ở cấp trình điều khiển đến các IP trên danh sách đen. Độ bảo mật cao, không yêu cầu mã (có thể cho là: rất an toàn, không yêu cầu mã).

1

nếu bạn nhận được địa chỉ IP như là một chuỗi, so sánh nó với một chuỗi có thể hiệu quả hơn chuyển đổi nó để nguyên đại diện

nhưng tôi muốn hồ sơ cả hai giải pháp để chắc chắn, nếu một vài mili giây (nano giây !) sẽ là vấn đề đối với hoạt động này ;-)

2

Bạn có vấn đề với hiệu quả hiện tại không?

Nếu vậy thì bằng mọi cách, hãy viết mã (hoặc mã giả) và chúng tôi có thể chọn tại xác chết.

Nếu không thì tôi khuyên bạn nên thử một cái gì đó đơn giản như lưu trữ các mục trong danh sách được sắp xếp và sử dụng Sort()Find() hiện tại của môi trường của bạn.

5

Bạn có nghĩa là nếu bạn nên so sánh nó dưới dạng chuỗi văn bản hoặc chuyển đổi int thành int và so sánh dưới dạng int?

Đó thường không phải là nút cổ chai trong loại tra cứu này. bạn chỉ có thể thử triển khai cả hai phương pháp và xem phương thức nào chạy nhanh hơn.

Vấn đề thực sự với tra cứu địa chỉ IP thường là truy vấn hiệu quả, lợi dụng thực tế là bạn đang xử lý địa chỉ IP và không chỉ là số ngẫu nhiên. để thực hiện việc này, bạn có thể tra cứu LC trie và có thể this article

Rõ ràng điều này sẽ chỉ quan tâm đến bạn nếu danh sách đen của bạn chứa hàng chục nghìn hoặc hàng triệu mục nhập. Nếu nó chỉ có 10-20 mục tìm kiếm tuyến tính nên được ưa thích và thực sự là câu hỏi thú vị hơn là so sánh văn bản so với so sánh số nguyên.

2

So sánh số nguyên nhanh hơn nhiều so với so sánh chuỗi.

Nếu bạn lưu trữ các số nguyên trong danh sách được sắp xếp, bạn có thể tìm thấy chúng nhanh hơn trong danh sách chưa được sắp xếp.

3

Tôi đã làm điều này và tôi đã thử nghiệm nó, bằng cách sử dụng một unsigned int (32 bit) là nhanh nhất - Tôi giả định rằng bạn đang so sánh điều này với chuỗi đại diện.

Một điều khác có thể giúp bạn khi tạo bảng, trong quá khứ tôi đã có 2 colums: LowIP và HighIP; bằng cách đó tôi đã có thể danh sách đen toàn bộ phạm vi của IP với 1 mục ghi và vẫn nhận được hiệu suất tốt bằng cách kiểm tra IP trong phạm vi.

3

Tôi đã từng thừa hưởng mã nơi ai đó nghĩ lưu trữ địa chỉ IP là 4 int là một điều thực sự tốt, ngoại trừ họ dành toàn bộ thời gian chuyển đổi sang/từ int's.

Việc giữ chúng dưới dạng chuỗi trong cơ sở dữ liệu dễ dàng hơn nhiều và chỉ yêu cầu một chỉ mục duy nhất. Bạn sẽ ngạc nhiên về cách máy chủ sql có thể lập chỉ mục các chuỗi như trái ngược với 4 cột số nguyên. Nhưng danh sách IP này không phải dành cho danh sách đen. Một chuyến đi vòng cơ sở dữ liệu khá tốn kém.

Nếu cơ sở dữ liệu quá mức, hãy lưu trữ chúng trong từ điển trong bộ nhớ, nhưng đó chỉ là phỏng đoán vì chúng tôi không biết bạn cần so sánh bao nhiêu. Vì hầu hết các hashcodes là 32-bit int, và địa chỉ IPv4 là 32 bit, địa chỉ IP chính nó có thể chỉ là một hashcode tốt.

Nhưng khi những người khác chỉ ra, tùy chọn tốt nhất có thể là giảm tải trên máy chủ của bạn và mua phần cứng chuyên dụng. Có lẽ bạn giữ IP của danh sách đen gần đây trong bộ nhớ và định kỳ xuất bản một bộ định tuyến mới cho bộ định tuyến.

Nếu bạn là người cố gắng tạo một số phần mềm bên trong bộ định tuyến, thì bạn sẽ cần phải tìm ra cuốn sách cấu trúc dữ liệu của mình và tạo một thứ gì đó giống như cây b.

+1

So sánh một biểu diễn không đúng (4 int) với một chuỗi khác (chuỗi) không phải là một sự so sánh công bằng thực sự. – MSalters

+1

Đó là phản ứng giai thoại của nguyên tắc KISS và việc lưu trữ địa chỉ IP dưới dạng chuỗi là đủ cho mục đích trong tầm tay. –

3

Radix hoặc PATRICIA Trie là cấu trúc tối ưu cho việc này.

Kiểm tra nguồn C cho dòng chảy công cụ: http://www.splintered.net/sw/flow-tools/

tôi làm việc trên năm này trước.

+0

Trang lưu lượng công cụ khá tốt!Có rất nhiều liên kết tốt ở đó, ví dụ: http://www.splintered.net/sw/flow-tools/SECURITY Cảm ơn bạn! –

5
static public bool IsEqual(string ToCompare, 
             string CompareAgainst) 
    { 

    return IPAddressToLongBackwards(ToCompare)==IPAddressToLongBackwards(CompareAgainst); 
    } 

static private uint IPAddressToLongBackwards(string IPAddr) 
    { 
    System.Net.IPAddress oIP=System.Net.IPAddress.Parse(IPAddr); 
    byte[] byteIP=oIP.GetAddressBytes(); 


    uint ip=(uint)byteIP[0]<<24; 
    ip+=(uint)byteIP[1]<<16; 
    ip+=(uint)byteIP[2]<<8; 
    ip+=(uint)byteIP[3]; 

    return ip; 
    } 

Nếu tôi hiểu chính xác đây là mã để so sánh hai Địa chỉ IP, bạn có muốn điều này không? bạn có thể làm thêm những việc như vậy giống như ...

static public bool IsGreater(string ToCompare, 
           string CompareAgainst) 
    { 

    return IPAddressToLongBackwards(ToCompare)> 
     IPAddressToLongBackwards(CompareAgainst); 
    } 

vì bạn đã nhận byte địa chỉ ... Nếu bạn ưng ý thì bỏ phiếu cho tôi UP nhưng xin đừng bỏ phiếu cho tôi tiêu cực

Các vấn đề liên quan