IP 地址

@2012-04-20 新版功能: 创建, IPv6 local address

在 @2019-02-16 版更改: 增加 IPv4, add more address from RFC

参考 IP address

IPv4

RFC 6890, (过时:RFC 5735

Address Block Present Use Reference
0.0.0.0/8 "This" Network RFC 1122#section-3.2.1.3
10.0.0.0/8 Private-Use Networks RFC 1918
127.0.0.0/8 Loopback RFC 1122#section-3.2.1.3
100.64.0.0/10 Shared Address Space RFC 6598
169.254.0.0/16 Link Local RFC 3927
172.16.0.0/12 Private-Use Networks RFC 1918
192.0.0.0/24 IETF Protocol Assignments RFC 5736
192.0.0.0/29 DS-Lite RFC 6333
192.0.2.0/24 TEST-NET-1 RFC 5737
192.88.99.0/24 6to4 Relay Anycast RFC 3068
192.168.0.0/16 Private-Use Networks RFC 1918
198.18.0.0/15 Network Interconnect Device Benchmark Testing RFC 2544
198.51.100.0/24 TEST-NET-2 RFC 5737
203.0.113.0/24 TEST-NET-3 RFC 5737
224.0.0.0/4 Multicast RFC 3171
240.0.0.0/4 Reserved for Future Use RFC 1112#section-4
255.255.255.255/32 Limited Broadcast RFC 919#section-7 RFC 922#section-7
  • Private addresses

    • 10.0.0.0/8 (10.0.0.0 - 10.255.255.255)
    • 172.16.0.0/12 (172.16.0.0 – 172.31.255.255)
    • 192.168.0.0/16 (192.168.0.0 – 192.168.255.255)
  • Shared addresses

    • 100.64.0.0/10
      1. However, Shared Address Space has limitations in its use that the current [RFC 1918] private address space does not have.
      2. In particular, Shared Address Space can only be used in Service Provider networks or on routing equipment that is able to do address translation across router interfaces when the addresses are identical on two different interfaces.
  • Link local

    • 169.254.0.0/16

      Allocated for communication between hosts on a single link. Hosts obtain these addresses by auto-configuration, such as when a DHCP server cannot be found.

IPv6

连接测试网站: http://ipv6-test.com

Address Block Present Use Reference
::1/128 Loopback Address RFC 4291
::/128 Unspecified Address RFC 4291
64:ff9b::/96 IPv4-IPv6 Translat RFC 6052
::ffff:0:0/96 IPv4-mapped Address RFC 4291
100::/64 Discard-Only Address Block RFC 6666
2001::/23 IETF Protocol Assignments RFC 2928
2001::/32 TEREDO RFC 4380
2001:2::/48 Benchmarking RFC 5180
2001:db8::/32 Documentation RFC 3849
2001:10::/28 ORCHID (not after 201403) RFC 4843
2002::/16 6to4 RFC 3056
fc00::/7 Unique-Local RFC 4193
fe80::/10 Linked-Scoped Unicast RFC 4291

The Local IPv6 addresses are created using a pseudo-randomly allocated global ID. They have the following format:

   | 7 bits |1|  40 bits   |  16 bits  |          64 bits           |
   +--------+-+------------+-----------+----------------------------+
   | Prefix |L| Global ID  | Subnet ID |        Interface ID        |
   +--------+-+------------+-----------+----------------------------+

Where:

   Prefix            FC00::/7 prefix to identify Local IPv6 unicast
                     addresses.

   L                 Set to 1 if the prefix is locally assigned.
                     Set to 0 may be defined in the future.  See
                     Section 3.2 for additional information.

   Global ID         40-bit global identifier used to create a
                     globally unique prefix.  See Section 3.2 for
                     additional information.

   Subnet ID         16-bit Subnet ID is an identifier of a subnet
                     within the site.

   Interface ID      64-bit Interface ID as defined in [ADDARCH].

Use following program to generate Locally Assigned Global ID.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
# -*- mode: python ; ispell-local-dictionary: "american" -*-
"""
Generate 'Locally Assigned Global IDs' according to RFC 4193

The Algorithm as described in the RFC:

     1) Obtain the current time of day in 64-bit NTP format [NTP].
     2) Obtain an EUI-64 identifier from the system running this
        algorithm.  If an EUI-64 does not exist, one can be created from
        a 48-bit MAC address as specified in [ADDARCH].  If an EUI-64
        cannot be obtained or created, a suitably unique identifier,
        local to the node, should be used (e.g. system serial number).
     3) Concatenate the time of day with the system-specific identifier
        creating a key.
     4) Compute an SHA-1 digest on the key as specified in [FIPS, SHA1];
        the resulting value is 160 bits.
     5) Use the least significant 40 bits as the Global ID.
     6) Concatenate FC00::/7, the L bit set to 1, and the 40 bit Global
        ID to create a Local IPv6 address prefix.
"""

# Required Python 2.4 (or better)
#
# History:
# 2012-02-09:
#    - Bugfix: import error.
# 2010-12-22:
#    - Bugfix: calculation of NTP format was wrong (Thanks to Sergei
#      Zhirikov for pointing this out)
#    - Bugfix: "Encapsulated MAC-48 values" use FFFF, not FFFE (again
#      thanks to Sergei Zhirikov for pointing this out)
#    - Enhancement: Use Python module ``uuid`` (new in Python 2.4) to
#      get the MAC address platform independent
# 2005-07-08:
#    - Initial Release
#

__author__ = "Hartmut Goebel <h.goebel@goebel-consult.de>"
__copyright__ = "(C) Copyright 2005-2012 by Hartmut Goebel"
__licence__ = "GNU Public Licence (GPL), Version 3 or later"
__version__ = "0.3.2"

import time
import struct
import commands
import re
import socket
import sha
import uuid

# from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/117211
TIME1970 = 2208988800L      # Thanks to F.Lundh

def _get_time_ntpformat():
    """
    Get current time of day in 64-bit NTP format.
    """
    # Calculation of fractal part adopted from
    # <http://pypi.python.org/pypi/ntplib/>, thanks to
    # Charles-Francois Natali and the NTP FAQ
    # <http://www.ntp.org/ntpfaq/NTP-s-algo.htm#AEN1895>
    t = time.time() + TIME1970
    int_part = long(t)
    frac_part = long( (t-int_part) * 2**32 )
    t = struct.pack('>LL', int_part, frac_part)
    return t

def _get_EUI64():
    '''
    Create an EUI-64 identifier from the MAC address
    according to "Encapsulated MAC-48 values" in
    http://standards.ieee.org/regauth/oui/tutorials/EUI64.html
    '''
    # get the MAC of some interface
    mac = '%012x' % uuid.getnode()
    mac = [mac[i:i+2] for i in range(0, len(mac), 2)]
    # insert 'ffff'
    mac[3:3] = ['ff', 'ff']
    mac = map(lambda x: chr(int(x, 16)), mac)
    return ''.join(mac)


def calc_LAGID():
    """
    Calculate a single 'Locally Assigned Global ID' according to
    the algorithm described above.
    """
    # 1) current time of day in 64-bit NTP format
    t = _get_time_ntpformat();   assert len(t        ) * 8 == 64
    # 2) an EUI-64 identifier from the system running this algorithm
    eui64 = _get_EUI64();        assert len(eui64    ) * 8 == 64
    # 3) Concatenate
    key = t + eui64;             assert len(key      ) * 8 == 128
    # 4) Compute an SHA-1 digest on the key
    digest = sha.sha(key).digest()
    # 5) least significant 40 bits
    global_id = digest[-5:];     assert len(global_id) * 8 == 40
    # 6) Concatenate FC00::/7, the L bit set to 1, and global_id
    # fc00::/7 plus L bit set -> fd00::
    prefix = '\xfd' + global_id; assert len(prefix   ) * 8 == 48
    packed = prefix + '\0'* 10;  assert len(packed   ) * 8 == 128
    return packed


def calc_multiple_LAGIDs(num=10):
    """
    Calculate several 'Locally Assigned Global IDs' at once. A ramdom
    delay (up to 1 second) is put between calculations to decrease
    depentences between the generated values.

    This is usefull for getting severl LAG-IDs to select a 'nice' one.
    (Well, this may not be in the sence of the RFC ;-)

    num : Number of LAG-IDs to generate
    """
    import random
    ps = []
    for i in range(num):
        prefix = calc_LAGID()
        ps.append(prefix)
        time.sleep(random.random())
    return ps

def asString(prefix):
    """
    Convert a LAG-ID into a string representation (IPv6 address
    format).
    """
    if hasattr(socket, 'inet_ntop'):
        return socket.inet_ntop(socket.AF_INET6, prefix)
    else:
        import IPy
        prefix = '0x' + ''.join(['%02x' % ord(i) for i in  prefix ])
        return IPy.IP(prefix).strCompressed()

def _main():
    for prefix in calc_multiple_LAGIDs(10):
        print "Your 'Locally Assigned Global ID' is",
        print "%s/48" % asString(prefix)


if __name__ == '__main__':
    _main()