Chuyển đổi IP sang thập phân

Chuyển một địa chỉ IP sang thập phân, hex, nhị phân và bát phân, hoặc nhập bất kỳ số nào trong số đó để lấy lại IP. Mỗi octet được vẽ thành 8 bit kèm trọng số, để bạn theo dõi được phép tính.

Phân tích theo WHATWG URL Standard và inet_aton · phép tính 128 bit chính xác cho IPv6 · chạy ngay trong trình duyệt của bạn

Đọc theo dạng thập phân có dấu chấm

8 bit của mỗi octet, kèm trọng số198.51.100.77 = 3 325 256 781
Octet1286432168421HexTổng× trọng số= giá trị
19811000110C6128+64+4+2 = 198× 256³16 777 2163 321 888 768
128+64+4+2 × 256³ = 3 321 888 768
51001100113332+16+2+1 = 51× 256²65 5363 342 336
32+16+2+1 × 256² = 3 342 336
100011001006464+32+4 = 100× 25625625 600
64+32+4 × 256 = 25 600
77010011014D64+8+4+1 = 77× 1177
64+8+4+1 × 1 = 77
Tổng3 325 256 781
= 3 325 256 781
Ví dụ

Một địa chỉ IP, hoặc số thập phân, hex, nhị phân hay bát phân của nó để lấy lại IP. Chuyển đổi ngay trong trình duyệt của bạn; không gửi gì đi.

IPv4 · 32 bit

3325256781

198.51.100.77 dưới dạng một số 32 bit · Địa chỉ dành cho tài liệu (RFC 5737)

Cùng số đó trong code

SELECT INET_ATON('198.51.100.77');3325256781
SELECT '198.51.100.77'::inet - '0.0.0.0'::inet;3325256781
int(ipaddress.ip_address('198.51.100.77'))3325256781
ip2long('198.51.100.77')3325256781
Thập phân có dấu chấm
Thập phân
Hex
Octet nhị phân
Bát phân
Octet hex
Octet bát phân
Trong trình duyệt (mỗi URL đều mở 198.51.100.77)
Tên DNS ngược
Dạng IPv6 (ánh xạ)
IPv4 → IPv6

Làm sao chuyển địa chỉ IP sang thập phân?

Nhân bốn số lần lượt với 256³, 256², 256 và 1 rồi cộng lại: 192.168.1.1 là 192 × 16777216 + 168 × 65536 + 1 × 256 + 1 = 3232235777.

Một địa chỉ IPv4 là một số 32 bit được viết thành bốn mảnh 8 bit, nên dạng có dấu chấm và dạng thập phân là cùng một giá trị. Tài liệu của MySQL lấy ví dụ 10.0.5.9 = 167773449.

192.168.1.1 thành một số: mỗi phần nhân với trọng số của vị trí, rồi cộng lại.
Công cụ chuyển đổi IP sang thập phân cho thấy các bit và trọng số của mỗi octet cộng lại thành một con sốCông cụ chuyển đổi IP sang thập phân cho thấy các bit và trọng số của mỗi octet cộng lại thành một con sốNhập dạng nào cũng đượcCó dấu chấm, thập phân, hex, nhị phân, bát phân hay URL: ô nhập đọc được tất cả.Bit và trọng sốMỗi bit 1 cộng thêm trọng số của nó: 128 + 64 + 4 + 2 = 198.× 256³, 256², 256, 1Mỗi octet nhân với trọng số của nó, rồi cộng tổng.Ra đủ mọi dạngHex, nhị phân, bát phân và các URL mà trình duyệt chấp nhận, mỗi dạng đều có nút sao chép.Con sốCả địa chỉ dưới dạng một số 32 bit, sẵn sàng sao chép, kèm loại địa chỉ.
198.51.100.77 theo từng bit: trọng số của mỗi octet, rồi × 256³, 256², 256 và 1, cộng lại thành 3325256781.

Làm sao chuyển số thập phân sang địa chỉ IP?

Chia cho 16777216, rồi chia số dư cho 65536, rồi cho 256: ba thương và số dư cuối cùng là bốn số, nên 3232235777 là 192.168.1.1.

Nhập con số vào công cụ và nó làm đúng như vậy, kèm cả hex, nhị phân, bát phân và các dạng trình duyệt chấp nhận. Số lớn hơn 4294967295 không phải địa chỉ IPv4; công cụ đọc chúng là số IPv6 và nói rõ điều đó.

3232235777 trở lại 192.168.1.1 bằng phép chia.

Làm sao chuyển địa chỉ IP sang nhị phân?

Viết mỗi số trong bốn số thành 8 bit với các trọng số 128, 64, 32, 16, 8, 4, 2 và 1: 192 là 128 + 64, nên là 11000000, và 192.168.1.1 là 11000000.10101000.00000001.00000001.

Đi qua các trọng số từ trái sang: viết 1 và trừ đi khi trọng số còn vừa, nếu không thì viết 0. Với 168: 128 vừa (còn 40), 64 không vừa, 32 vừa (còn 8), 16 không vừa, 8 vừa, nên là 10101000. Để đổi ngược từ nhị phân, cộng trọng số của các bit 1.

Mỗi octet của 192.168.1.1 so với các trọng số từ 128 đến 1.

Làm sao chuyển địa chỉ IP sang hex?

Chia 8 bit của mỗi octet thành hai nửa 4 bit và viết mỗi nửa thành một chữ số hex: 192 là 1100 0000, tức C0, nên 192.168.1.1 là 0xC0A80101.

Hex cũng là cách IPv6 viết một địa chỉ IPv4 được nhúng: ::ffff:c0a8:101 là 192.168.1.1. Trình duyệt chấp nhận số hex làm host: http://0xC0A80101/ mở 192.168.1.1.

Bốn bit cho mỗi chữ số hex: 192.168.1.1 là C0 A8 01 01.

Vì sao http://3232235777 mở 192.168.1.1?

Vì trình duyệt đọc một host chỉ gồm chữ số thành địa chỉ IPv4 theo bất kỳ dạng inet_aton cũ nào, kể cả một số thập phân duy nhất, rồi tải địa chỉ có dấu chấm.

Mỗi phần có thể là thập phân (URL Standard), hex với 0x hoặc bát phân với số 0 đứng đầu, và khi có ít hơn bốn phần thì phần cuối lấp đầy các byte còn lại. Vì vậy http://192.168.1/ mở 192.168.0.1, không phải 192.168.1.1. ping và curl cũng chấp nhận các dạng này.

Số vượt quá 32 bit, chữ số 8 hoặc 9 trong một phần bắt đầu bằng 0, và phần thứ năm đều bị từ chối.

Gõ vào thanh địa chỉMở ra
http://3232235777/192.168.1.1
http://0xC0A80101/192.168.1.1
http://0300.0250.1.1/192.168.1.1
http://127.1/127.0.0.1
http://192.168.1/192.168.0.1
http://4294967296/Bị từ chối
http://09/Bị từ chối
http://192.0.2.1.5/Bị từ chối
Trình phân tích URL của WHATWG xử lý từng host như thế nào.

Vì sao các cách viết khác của địa chỉ IP quan trọng với bảo mật?

Vì một bộ lọc so sánh địa chỉ dưới dạng văn bản có thể bị đánh lừa: 2130706433, 0x7f.1, 127.1 và ::ffff:127.0.0.1 đều là 127.0.0.1, nên bộ lọc phải so sánh giá trị số, không phải chuỗi.

OWASP liệt kê các cách mã hóa này trong số những cách vượt qua lớp phòng thủ SSRF. Đã có thư viện phát hành kèm lỗi này: các gói npm netmask và ip, ipaddress của Python và gói net của Go đều từng đọc sai số 0 đứng đầu hoặc các dạng viết khác, và sau đó đã được sửa.

Hãy phân tích bằng một trình đọc nghiêm ngặt, chuyển sang số, rồi mới so sánh dải. Chặn cả các địa chỉ ánh xạ IPv4 của những dải bị chặn.

deny 127.0.0.1

So sánh dạng chuỗi

127.0.0.1bị chặn

2130706433lọt qua

0x7f.1lọt qua

127.1lọt qua

::ffff:127.0.0.1lọt qua

So sánh dạng số

127.0.0.12130706433 · bị chặn

21307064332130706433 · bị chặn

0x7f.12130706433 · bị chặn

127.12130706433 · bị chặn

::ffff:127.0.0.12130706433 · bị chặn

CVE-2021-28918netmask (npm)CVE-2021-29418netmask (npm)CVE-2021-29424Net::Netmask (Perl)CVE-2021-29921Python ipaddressCVE-2021-29923Go netCVE-2024-29415ip (npm)
Một quy tắc, năm cách viết địa chỉ loopback; tiếp theo là các cảnh báo bảo mật.

Làm sao chuyển địa chỉ IPv6 sang thập phân?

Làm tương tự với tám nhóm 16 bit: 2001:db8::1 là 42540766411282592856903984951653826561, một số dài tới 39 chữ số cần đến BigInt trong JavaScript.

Có 2^128 địa chỉ IPv6. Số trong JavaScript chỉ lưu chính xác số nguyên tới 2^53 − 1, nên phép tính thông thường âm thầm làm tròn các giá trị IPv6. int(ipaddress.ip_address(…)) của Python thì chính xác.

2001:db8::1 dưới dạng một số, và một số JavaScript thông thường biến nó thành gì.

Làm sao chuyển địa chỉ IP sang số trong code và cơ sở dữ liệu?

Dùng hàm có sẵn của nền tảng với kiểu không dấu: INET_ATON() của MySQL vào INT UNSIGNED, phép trừ inet của PostgreSQL, int(ipaddress.ip_address(…)) của Python, và >>> 0 sau các phép dịch bit trong JavaScript.

Số nguyên 32 bit có dấu không chứa được các địa chỉ từ 128.0.0.0 trở lên: << của JavaScript cho ra -1062731519 với 192.168.1.1, và ip2long() của PHP ra số âm trên bản build 32 bit. Với IPv6, MySQL dùng INET6_ATON() và VARBINARY(16).

› SELECT INET_ATON('192.168.1.1'), INET_NTOA(3232235777);
3232235777 | 192.168.1.1

MySQL 8.4

› SELECT '192.168.1.1'::inet - '0.0.0.0'::inet,
       '0.0.0.0'::inet + 3232235777;
3232235777 | 192.168.1.1

PostgreSQL 16

› import ipaddress
int(ipaddress.ip_address('192.168.1.1')), ipaddress.IPv4Address(3232235777)
(3232235777, IPv4Address('192.168.1.1'))

Python ipaddress

› '192.168.1.1'.split('.').reduce((n, o) => (n << 8) | +o, 0) >>> 0
3232235777

JavaScript

› echo ip2long('192.168.1.1'), ' ', long2ip(3232235777);
3232235777 192.168.1.1

PHP 8

192.168.1.1 thành số và ngược lại trong hai cơ sở dữ liệu và ba ngôn ngữ.

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

192.168.1.1 ở dạng thập phân là bao nhiêu?

3232235777. Nhân mỗi phần với trọng số của nó rồi cộng lại: 192 × 16777216 + 168 × 65536 + 1 × 256 + 1 = 3232235777. Cùng con số đó là 0xC0A80101 ở dạng hex và 11000000.10101000.00000001.00000001 ở dạng nhị phân. Trình duyệt cũng chấp nhận nó làm host, nên http://3232235777/ mở cùng địa chỉ với http://192.168.1.1/.

Giá trị thập phân lớn nhất của một địa chỉ IPv4 là bao nhiêu?

4294967295, tức 255.255.255.255. Địa chỉ IPv4 là một số 32 bit, nên có 2^32 = 4294967296 địa chỉ, từ 0 (0.0.0.0) đến 4294967295. Số lớn hơn không phải địa chỉ IPv4: trình duyệt từ chối http://4294967296/, còn công cụ này đọc những số như vậy thành giá trị IPv6 128 bit và báo cho bạn biết.

Làm sao chuyển 3232235777 trở lại địa chỉ IP?

Chia cho 16777216 để được phần đầu: 192, dư 11010305. Chia số dư đó cho 65536 để được phần thứ hai: 168, dư 257. Chia 257 cho 256 để được phần thứ ba: 1, dư 1, đó là phần thứ tư. Kết quả là 192.168.1.1. Nhập con số vào công cụ, nó sẽ cho thấy cả các bit của từng octet.

Số 0 đứng đầu như 010 trong địa chỉ IP có nghĩa là gì?

Tùy chương trình. Trình duyệt và inet_aton đọc một phần có số 0 đứng đầu là bát phân, nên 192.0.2.010 là 192.0.2.8, trong khi các công cụ bỏ qua số 0 đọc thành 192.0.2.10. Python và Go nay từ chối thẳng những địa chỉ như vậy, sau các lỗi mà hai cách đọc khác nhau đã để yêu cầu lọt qua bộ lọc IP. Đừng bao giờ viết số 0 đứng đầu trong địa chỉ IPv4.

Vì sao 192.168.1 mở 192.168.0.1?

Vì một địa chỉ ba phần dùng phần cuối để lấp đầy 16 bit cuối. Trong 192.168.1, số 1 cuối cùng trở thành số 16 bit 1, tức 0.1, nên địa chỉ là 192.168.0.1. Đó là cách inet_aton và trình duyệt đọc dạng rút gọn, và 192.168.257 sẽ là 192.168.1.1. Kiểu cidr của PostgreSQL đọc 192.168.1 theo cách khác, là mạng 192.168.1.0/24.

Làm sao tự tay chuyển địa chỉ IP sang nhị phân?

Với mỗi số trong bốn số, đi qua các trọng số 128, 64, 32, 16, 8, 4, 2 và 1: viết 1 và trừ đi khi trọng số còn vừa, nếu không thì viết 0. Với 168: 128 vừa (còn 40), 64 không vừa, 32 vừa (còn 8), 16 không vừa, 8 vừa (còn 0), nên là 10101000. Nối bốn nhóm 8 bit bằng dấu chấm.

Làm sao lưu địa chỉ IP dưới dạng số trong MySQL?

Chuyển bằng INET_ATON('10.0.5.9'), hàm trả về 167773449, và lưu kết quả vào cột INT UNSIGNED: INT có dấu không chứa được địa chỉ lớn hơn 127.255.255.255. INET_NTOA chuyển con số trở lại văn bản. Với IPv6, dùng INET6_ATON và cột VARBINARY(16), vì giá trị 128 bit không vừa với kiểu số nguyên nào. Đừng dựa vào INET_ATON cho các dạng rút gọn như 127.1.

Vì sao số IP của tôi bị âm trong JavaScript hoặc PHP?

Vì nó đã được xử lý như một số nguyên 32 bit có dấu. Toán tử << của JavaScript trả về kết quả có dấu, nên 192.168.1.1 dựng bằng phép dịch bit cho ra -1062731519; thêm >>> 0 để có 3232235777. ip2long của PHP cũng như vậy trên bản build 32 bit, nơi sprintf('%u', …) in ra giá trị không dấu. Chỉ các địa chỉ từ 128.0.0.0 trở lên bị ảnh hưởng, nên lỗi này thường không bị phát hiện.

Có thể chuyển địa chỉ IPv6 sang thập phân không?

Có. Địa chỉ IPv6 là một số 128 bit, nên 2001:db8::1 là 42540766411282592856903984951653826561, và giá trị lớn nhất có 39 chữ số. Số JavaScript thông thường mất độ chính xác khi vượt quá 2^53, nên công cụ phải dùng BigInt, và một số công cụ chuyển đổi trực tuyến tính sai các chữ số cuối. int(ipaddress.ip_address('2001:db8::1')) của Python cho giá trị chính xác.

http://0x7f000001/ có giống 127.0.0.1 không?

Có. Trình duyệt và nhiều công cụ dòng lệnh đọc một host gồm các chữ số hex sau 0x thành một số 32 bit, nên 0x7f000001, 2130706433, 0x7f.1 và 127.1 đều là 127.0.0.1, địa chỉ loopback. Đó là lý do bộ lọc bảo mật phải so sánh giá trị số thay vì văn bản, đúng như khuyến nghị của RFC 3986 và cheat sheet SSRF của OWASP.