পাইপনের কোনও নেটওয়ার্কে একটি আইপি রয়েছে কিনা তা আমি কীভাবে পরীক্ষা করতে পারি?


102

একটি আইপি ঠিকানা দেওয়া (192.168.0.1 বলুন), পাইথনের কোনও নেটওয়ার্কে (192.168.0.0/24 বলুন) এটি কিনা আমি কীভাবে পরীক্ষা করব?

আইপি অ্যাড্রেস ম্যানিপুলেশনের জন্য পাইথনে সাধারণ সরঞ্জাম রয়েছে? হোস্ট লুকআপসের মতো স্টাফ, আইপি অ্যাড্রেস ইন ইন, নেটমাস্ক ইনট্রেটিভের সাথে নেটওয়ার্ক অ্যাড্রেস ইত্যাদি? আশা করি 2.5 স্ট্যান্ডার্ড পাইথন লাইব্রেরিতে।


এই প্রশ্নটি খুব পুরানো ২.x উত্তরের জন্য ঠিক মতন হিসাবে মনে হচ্ছে তবে এটি 3.x এর জন্য অপ্রচলিত দেখুন "পাইথন / পান্ডাস আইপি ঠিকানা / সিআইডিআর তুলনা করুন" এর জন্য ক্যানোনিকালগুলি কীভাবে সংগঠিত করবেন এবং নির্ধারণ করবেন?
smci

@ এসএমসি আমি কেন দেখছি না; এ phihag এর উত্তর stackoverflow.com/a/1004527/1709587 পাইথন 3 একটি পুরোপুরি ভাল উত্তর এবং এখানে হয়েছে 2014. যেহেতু আমি আপনার সম্পাদনার যে উত্তর invalidated ফিরে ঘূর্ণিত গেছেন।
মার্ক অ্যামেরি

@ স্টায়েল - আপনার উত্তরটি এখানে এমন একের সাথে আপডেট করা উচিত যেখানে সমালোচনামূলক ত্রুটি নেই । অন্য উত্তরগুলি কোনও ত্রুটি ছাড়াই 1/10 তে একই কোড সম্পাদন করতে বিল্টিন গ্রন্থাগারগুলি ব্যবহার করে।
অ্যাডিসন

উত্তর:


28

এই নিবন্ধটি দেখায় যে আপনি অত্যধিক অতিরিক্ত প্রচেষ্টা ছাড়াই এটি socketএবং structমডিউলগুলি দিয়ে এটি করতে পারেন । আমি নিবন্ধে কিছুটা যুক্ত করেছি:

import socket,struct

def makeMask(n):
    "return a mask of n bits as a long integer"
    return (2L<<n-1) - 1

def dottedQuadToNum(ip):
    "convert decimal dotted quad string to long integer"
    return struct.unpack('L',socket.inet_aton(ip))[0]

def networkMask(ip,bits):
    "Convert a network address to a long integer" 
    return dottedQuadToNum(ip) & makeMask(bits)

def addressInNetwork(ip,net):
   "Is an address in a network"
   return ip & net == net

address = dottedQuadToNum("192.168.1.1")
networka = networkMask("10.0.0.0",24)
networkb = networkMask("192.168.0.0",24)
print (address,networka,networkb)
print addressInNetwork(address,networka)
print addressInNetwork(address,networkb)

এই ফলাফলগুলি:

False
True

আপনি যদি কেবল একটি একক ফাংশন চান যা স্ট্রিংগুলি লাগে তবে এটি দেখতে এরকম হবে:

import socket,struct

def addressInNetwork(ip,net):
   "Is an address in a network"
   ipaddr = struct.unpack('L',socket.inet_aton(ip))[0]
   netaddr,bits = net.split('/')
   netmask = struct.unpack('L',socket.inet_aton(netaddr))[0] & ((2L<<int(bits)-1) - 1)
   return ipaddr & netmask == netmask

8
অতিরিক্তভাবে, স্ট্রাক্ট.নপ্যাক ('এল', সকেট.ইন_টোন (আইপি)) [0] আর্কিটেকচারে ব্যর্থ হবে যেখানে 'এল' চারটি বাইটের চেয়ে আলাদা কিছুতে আনপ্যাক করে, প্রান্তিকতা নির্বিশেষে।
রাফা ডাউগার্ড

5
return struct.unpack('<L',socket.inet_aton(ip))[0]
রাফালের মন্তব্যে অবিরত

12
আমি মনে করি আপনার সমাধানটিতে একটি গুরুতর ত্রুটি রয়েছে: addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True(আমি আমার 64 বিট ওএসে 'এল' কে '<এল' তে রূপান্তরিত করেছি)
তাহা জাহাঙ্গীর

22
সতর্কতা: এই দ্রষ্টব্যটির একটি গুরুতর ত্রুটি রয়েছে:addressInNetwork('172.7.1.1', '172.3.0.0/16') -> True
তাহা জাহাঙ্গীর

7
এই উত্তরে একটি বাগ রয়েছে । : উত্তর দেখার stackoverflow.com/questions/819355/...
Debanshu কুণ্ডু

159

আমি তার জন্য নেটড্যাডার ব্যবহার করতে চাই:

from netaddr import CIDR, IP

if IP("192.168.0.1") in CIDR("192.168.0.0/24"):
    print "Yay!"

আরনো_ভি মন্তব্যগুলিতে যেমন উল্লেখ করেছেন, নেটডাড্রারের নতুন সংস্করণটি এটির মতো করে:

from netaddr import IPNetwork, IPAddress
if IPAddress("192.168.0.1") in IPNetwork("192.168.0.0/24"):
    print "Yay!"

>>> নেটড্ডারআল_ম্যাচিং_সিডারস ("192.168.0.1", ["192.168.0.0/24", "212.11.64.0/19 "]) [আইপি নেট নেটওয়ার্ক ('192.168.0.0/24')]

22
বা নতুন সংস্করণে: নেটড্রেডারের আমদানি থেকে আইপনেটওয়ার্ক, আইপিএড্রেস আইপিএড্রেস ("192.168.0.1") আইপিনেটওয়ার্কে ("192.168.0.0/24")
আরনো_ভি

149

ব্যবহার IPADDRESS ( 3.3 থেকে stdlib মধ্যে , 2.6 / 2.7 জন্য PyPi এ ):

>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1') in ipaddress.ip_network('192.168.0.0/24')
True

আপনি যদি এইভাবে অনেকগুলি আইপি ঠিকানাগুলি মূল্যায়ন করতে চান তবে আপনি সম্ভবত নেটমাস্কের সম্মুখভাগটি গণনা করতে চান,

n = ipaddress.ip_network('192.0.0.0/16')
netw = int(n.network_address)
mask = int(n.netmask)

তারপরে, প্রতিটি ঠিকানার জন্য, একটির সাথে বাইনারি উপস্থাপনা গণনা করুন

a = int(ipaddress.ip_address('192.0.43.10'))
a = struct.unpack('!I', socket.inet_pton(socket.AF_INET, '192.0.43.10'))[0]
a = struct.unpack('!I', socket.inet_aton('192.0.43.10'))[0]  # IPv4 only

অবশেষে, আপনি কেবল পরীক্ষা করতে পারেন:

in_network = (a & mask) == netw

4
সাবধান, অজগর-আইপ্যাড্ডার আমাদের জন্য যথেষ্ট ধীর আচরণ করেছিল, তাই এটি এমন কিছু ক্ষেত্রে অনুপযুক্ত হতে পারে যেখানে ঘন ঘন প্রচুর তুলনা করা প্রয়োজন। ওয়াইএমএমভি, তাই নিজেকে মাপুন।
drdaeman

কিছু সংস্করণে, আপনাকে পাইথন স্ট্র্যাপের মতো একটি ইউনিকোড স্ট্রিং সরবরাহ করতে হবে, যেমন ipaddress.ip_address(u'192.168.0.1') in ipaddress.ip_network(u'192.168.0.0/24')
মুনডোগি

4
আমি উদ্বিগ্ন ছিল যে এই পদ্ধতিটি নেটওয়ার্কের ঠিকানাগুলির তালিকার উপরে পুনরাবৃত্তি করছে, তবে আইপ্যাড্রেস মডিউলটি __contains__একটি কার্যকর উপায়ে নেটওয়ার্ক ও সম্প্রচারের ঠিকানাগুলির পূর্ণসংখ্যার উপস্থাপনের সাথে তুলনা করে একটি কার্যকর উপায়ে ওভাররাইড করে assured ।
অবতারফোফ 2

30

পাইথন 3 এর জন্য

import ipaddress
ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/24')
ipaddress.IPv4Address('192.168.1.1') in ipaddress.IPv4Network('192.168.0.0/16')

আউটপুট:

False
True

4
স্ট্যান্ডার্ড লিব চতুর বিটওয়াস চেকিং ব্যবহার করে তাই এটি এখানে সর্বাধিক অনুকূল সমাধান। github.com/python/cpython/blob/3.8/Lib/ipaddress.py#L690
রকেটস্পেসার

11

এই কোডটি আমার জন্য লিনাক্স x86 এ কাজ করছে। আমি প্রকৃতপক্ষে ইস্যুগুলি সম্পর্কে কোনও চিন্তাভাবনা করি নি, তবে আমি এটি "আইপ্যাড্ডার" মডিউলটির বিপরীতে 8 টি বিভিন্ন নেটওয়ার্ক স্ট্রিংয়ের সাথে পরীক্ষিত 200 কে আইপি অ্যাড্রেস ব্যবহার করে পরীক্ষা করেছি এবং আইপ্যাডডারের ফলাফলগুলি এই কোডের মতোই।

def addressInNetwork(ip, net):
   import socket,struct
   ipaddr = int(''.join([ '%02x' % int(x) for x in ip.split('.') ]), 16)
   netstr, bits = net.split('/')
   netaddr = int(''.join([ '%02x' % int(x) for x in netstr.split('.') ]), 16)
   mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
   return (ipaddr & mask) == (netaddr & mask)

উদাহরণ:

>>> print addressInNetwork('10.9.8.7', '10.9.1.0/16')
True
>>> print addressInNetwork('10.9.8.7', '10.9.1.0/24')
False

সুন্দর এবং দ্রুত। কয়েকটি সাধারণ লজিক অপারেশনের জন্য লাইব্রেরির দরকার নেই।
ক্রিস কোস্টন

7

মডিউলগুলি যখন প্রয়োজন হয় না তখন আমি তাদের ব্যবহার করার ভক্ত নই। এই কাজের জন্য কেবল সাধারণ গণিতের প্রয়োজন, কাজটি করার জন্য এখানে আমার সাধারণ কাজটি করা হল:

def ipToInt(ip):
    o = map(int, ip.split('.'))
    res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
    return res

def isIpInSubnet(ip, ipNetwork, maskLength):
    ipInt = ipToInt(ip)#my test ip, in int form

    maskLengthFromRight = 32 - maskLength

    ipNetworkInt = ipToInt(ipNetwork) #convert the ip network into integer form
    binString = "{0:b}".format(ipNetworkInt) #convert that into into binary (string format)

    chopAmount = 0 #find out how much of that int I need to cut off
    for i in range(maskLengthFromRight):
        if i < len(binString):
            chopAmount += int(binString[len(binString)-1-i]) * 2**i

    minVal = ipNetworkInt-chopAmount
    maxVal = minVal+2**maskLengthFromRight -1

    return minVal <= ipInt and ipInt <= maxVal

তারপরে এটি ব্যবহার করতে:

>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',24) 
True
>>> print isIpInSubnet('66.151.97.193', '66.151.97.192',29) 
True
>>> print isIpInSubnet('66.151.96.0', '66.151.97.192',24) 
False
>>> print isIpInSubnet('66.151.97.0', '66.151.97.192',29) 

এটি হ'ল এটি অন্তর্ভুক্ত মডিউলগুলির সাথে উপরের সমাধানগুলির চেয়ে অনেক দ্রুত।


{TypeError}'map' object is not subscriptable। আপনি একটি প্রয়োজন o = list(o)পরo = map(int, ip.split('.'))
gies0r

7

Python3 ব্যবহার IPADDRESS :

import ipaddress

address = ipaddress.ip_address("192.168.0.1")
network = ipaddress.ip_network("192.168.0.0/16")

print(network.supernet_of(ipaddress.ip_network(f"{address}/{address.max_prefixlen}")))

ব্যাখ্যা

আপনি কোনও আইপি অ্যাড্রেসকে নেটওয়ার্ক হিসাবে সর্বাধিক সম্ভব নেটমাস্ক ( /32আইপিভি 4 এর জন্য, আইপিভি /1286 এর জন্য) ভাবতে পারেন

পরীক্ষা করা হচ্ছে কিনা 192.168.0.1হয় 192.168.0.0/16মূলত চেক হিসাবে একই কিনা 192.168.0.1/32একটি সাবনেট হয়192.168.0.0/16


... নিশ্চিত নয় কেন এই উত্তরটি শীর্ষে নেই (এখনও)।
ফিলিপ্পো ভিটালে

6

আমি ডেভ ওয়েবের সমাধানটি চেষ্টা করেছিলাম তবে কিছু সমস্যা হিট করেছি:

বেশিরভাগ মৌলিকভাবে - মাস্কের সাহায্যে আইপি ঠিকানাটি অ্যান্ডিংয়ের মাধ্যমে একটি ম্যাচ পরীক্ষা করা উচিত, তারপরে ফলাফলটি ঠিকানার ঠিকানার সাথে মিলে যায় checking নেটওয়ার্ক ঠিকানার মতো আইপি অ্যাড্রেস অ্যান্ডিং নয় done

আমি আরও লক্ষ্য করেছি যে কেবলমাত্র এন্ডিয়ানদের আচরণকে উপেক্ষা করেই ধারাবাহিকতাটি বাঁচবে কেবলমাত্র অষ্টেটের সীমানায় মাস্কগুলির জন্য কাজ করবে (/ 24, / 16)। অন্যান্য মাস্কগুলি (/ 23, / 21) সঠিকভাবে কাজ করার জন্য আমি স্ট্রাক্ট কমান্ডগুলিতে "" এর চেয়ে বড় "যুক্ত করেছি এবং বাইনারি মাস্ক তৈরির জন্য কোডটি পরিবর্তন করে সমস্ত" 1 "দিয়ে শুরু করে (32-মাস্ক) বামে স্থানান্তরিত করেছি )।

অবশেষে, আমি একটি সাধারণ চেক যুক্ত করেছি যে নেটওয়ার্ক ঠিকানাটি মাস্কের জন্য বৈধ এবং কেবল একটি সতর্কতা প্রিন্ট না হলে এটি মুদ্রণ করুন।

ফলাফল এখানে:

def addressInNetwork(ip,net):
    "Is an address in a network"
    ipaddr = struct.unpack('>L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('>L',socket.inet_aton(netaddr))[0]
    ipaddr_masked = ipaddr & (4294967295<<(32-int(bits)))   # Logical AND of IP address and mask will equal the network address if it matches
    if netmask == netmask & (4294967295<<(32-int(bits))):   # Validate network address is valid for mask
            return ipaddr_masked == netmask
    else:
            print "***WARNING*** Network",netaddr,"not valid with mask /"+bits
            return ipaddr_masked == netmask

এটি 64৪-বিট ('এল' মানটি 32-বিট হওয়ায় ব্যর্থ হয়) এ নির্ভরযোগ্যভাবে কাজ করে বলে মনে হয় এবং একটি বুদ্ধিমান ক্রমে মানগুলি ফেরত দেয় (আইপিএডিডিআরটি 192.168.0.1 এর জন্য 0xC0A80001 হবে)। এটি "192.168.0.1/24" "192.168.0.1" এর জন্য নেটমাস্ক হিসাবে
অনুলিপি করেছে

পাইথন ২.৪
xlash

6

গৃহীত উত্তর কার্যকর হয় না ... যা আমাকে রাগিয়ে তুলছে। মুখোশটি পিছনের দিকে রয়েছে এবং এমন কোনও বিটগুলির সাথে কাজ করে না যা সাধারণ 8 বিট ব্লক নয় (যেমন / 24)। আমি উত্তরটি মানিয়ে নিয়েছি এবং এটি দুর্দান্তভাবে কাজ করে।

    import socket,struct

    def addressInNetwork(ip, net_n_bits):  
      ipaddr = struct.unpack('!L', socket.inet_aton(ip))[0]
      net, bits = net_n_bits.split('/')
      netaddr = struct.unpack('!L', socket.inet_aton(net))[0]
      netmask = (0xFFFFFFFF >> int(bits)) ^ 0xFFFFFFFF
      return ipaddr & netmask == netaddr

এখানে একটি ফাংশন যা একটি বিন্দুযুক্ত বাইনারি স্ট্রিংকে মাস্কিংয়ের কল্পনা করতে সহায়তা করে .. এমন ধরণের ipcalcআউটপুট দেয়।

    def bb(i):
     def s = '{:032b}'.format(i)
     def return s[0:8]+"."+s[8:16]+"."+s[16:24]+"."+s[24:32]

যেমন:

পাইথনের স্ক্রিন শট


5

2.5 এর জন্য স্ট্যান্ডার্ড লাইব্রেরিতে নেই, তবে আইপ্যাড্ডার এটিকে খুব সহজ করে তোলে। আমি বিশ্বাস করি এটি আইপ্যাড্রেস নামে ৩.৩ এ রয়েছে।

import ipaddr

a = ipaddr.IPAddress('192.168.0.1')
n = ipaddr.IPNetwork('192.168.0.0/24')

#This will return True
n.Contains(a)

এটি এখানে সমস্ত অগণিত পছন্দ থেকে আমার প্রিয় (মন্তব্য করার সময়, 2017)। ধন্যবাদ!
আরএসউ

4

মার্কের কোডটি প্রায় সঠিক। কোডটির একটি সম্পূর্ণ সংস্করণ হ'ল -

def addressInNetwork3(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(int(bits))))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-mask,32):
        bits |= (1 << i)
    return "%d.%d.%d.%d" % ((bits & 0xff000000) >> 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))

অবশ্যই উপরের হিসাবে একই উত্স থেকে ...

একটি খুব গুরুত্বপূর্ণ নোটটি হ'ল প্রথম কোডটিতে একটি ছোট ত্রুটি রয়েছে - আইপি ঠিকানা 255.255.255.255 কোনও সাবনেটের বৈধ আইপি হিসাবেও প্রদর্শিত হয়। আমার এই কোডটি কার্যকর করতে সময় পেল এবং সঠিক উত্তরের জন্য মার্ককে ধন্যবাদ জানাতে হয়েছিল।


চেষ্টা এবং পরীক্ষিত. এই পৃষ্ঠার সমস্ত সকেট /
কাঠামোর

4

"স্ট্রাক্ট" মডিউলটির উপর নির্ভর করা এন্ডিয়ান-নেস এবং টাইপ আকারগুলির সাথে সমস্যা সৃষ্টি করতে পারে এবং কেবল প্রয়োজন হয় না। অথবা সকেট.ইনেট_টোন ()। পাইথন ডটেড-কোয়াড আইপি অ্যাড্রেসগুলির সাথে খুব ভালভাবে কাজ করে:

def ip_to_u32(ip):
  return int(''.join('%02x' % int(d) for d in ip.split('.')), 16)

আমাকে প্রতিটি সকেট গ্রহণযোগ্য () কলটিতে মেনে চলার অনুমতিযোগ্য উত্স নেটওয়ার্কগুলির পুরো সেটটির বিপরীতে করা দরকার, সুতরাং আমি মুখোশ এবং নেটওয়ার্কগুলিকে পূর্ণসংখ্যা হিসাবে প্রতিরোধ করি:

SNS_SOURCES = [
  # US-EAST-1
  '207.171.167.101',
  '207.171.167.25',
  '207.171.167.26',
  '207.171.172.6',
  '54.239.98.0/24',
  '54.240.217.16/29',
  '54.240.217.8/29',
  '54.240.217.64/28',
  '54.240.217.80/29',
  '72.21.196.64/29',
  '72.21.198.64/29',
  '72.21.198.72',
  '72.21.217.0/24',
  ]

def build_masks():
  masks = [ ]
  for cidr in SNS_SOURCES:
    if '/' in cidr:
      netstr, bits = cidr.split('/')
      mask = (0xffffffff << (32 - int(bits))) & 0xffffffff
      net = ip_to_u32(netstr) & mask
    else:
      mask = 0xffffffff
      net = ip_to_u32(cidr)
    masks.append((mask, net))
  return masks

তারপরে আমি দ্রুত দেখতে পাচ্ছি যে প্রদত্ত আইপি networks নেটওয়ার্কগুলির মধ্যে একটির মধ্যে রয়েছে কিনা:

ip = ip_to_u32(ipstr)
for mask, net in cached_masks:
  if ip & mask == net:
    # matched!
    break
else:
  raise BadClientIP(ipstr)

কোনও মডিউল আমদানির প্রয়োজন নেই, এবং কোডটি খুব দ্রুত মিলছে।


এই ক্যাশেড_মাস্কগুলি কী উল্লেখ করা হয়েছে ??
আজিন

2

নেটড্রডিআর থেকে all_matching_cidrs আমদানি করুন

>>> from netaddr import all_matching_cidrs
>>> all_matching_cidrs("212.11.70.34", ["192.168.0.0/24","212.11.64.0/19"] )
[IPNetwork('212.11.64.0/19')]

এই পদ্ধতির ব্যবহার এখানে:

>>> help(all_matching_cidrs)

Help on function all_matching_cidrs in module netaddr.ip:

all_matching_cidrs(ip, cidrs)
    Matches an IP address or subnet against a given sequence of IP addresses and subnets.

    @param ip: a single IP address or subnet.

    @param cidrs: a sequence of IP addresses and/or subnets.

    @return: all matching IPAddress and/or IPNetwork objects from the provided
    sequence, an empty list if there was no match.

মূলত আপনি প্রথম যুক্তি হিসাবে আইপি ঠিকানা এবং দ্বিতীয় যুক্তি হিসাবে সিডারের একটি তালিকা সরবরাহ করেন। হিটগুলির একটি তালিকা ফেরত দেওয়া হয়েছে।


2
# এটি বাইট হ্যান্ডলিং করে অদ্ভুত বাইট ছাড়াই সঠিকভাবে কাজ করে
Def ঠিকানাআইনেটওয়ার্ক (আইপি, নেট):
    '' 'একটি নেটওয়ার্কে একটি ঠিকানা' ''
    ঠিকানাগুলিকে হোস্ট অর্ডারে রূপান্তর করুন, তাই শিফ্টগুলি আসলে অর্থবোধ করে
    আইপি = স্ট্রাক্ট.নপ্যাক ('> এল', সকেট.ইন_ইটন (আইপি)) [0]
    নেটড্রেড, বিটস = নেট.স্প্লিট ('/')
    নেটাড্ড্র = স্ট্রাক্ট.নপ্যাক ('> এল', সকেট.ইন_টোন (নেটাড্রেআর)) [0]
    # অবশ্যই সমস্ত মান, / 32 = শূন্য শিফট, / 0 = 32 শিফট বামে স্থানান্তরিত করতে হবে
    নেটমাস্ক = (0xffffffff << (32-আন্ত (বিট))) এবং 0xffffffff
    # নেটওয়ার্ক ঠিকানাটি যতক্ষণ না এটি যথাযথ নেটওয়ার্ক ঠিকানা হিসাবে মাস্ক করার দরকার নেই
    রিটার্ন (আইপি ও নেটমাস্ক) == নেটড্যাড্র 

ভুল netmaskমানগুলির কারণে কোডটি 64-বিট ওএসে সঠিকভাবে কাজ করে নি । আমি এটি ঠিক করার জন্য একটি স্বাধীনতা গ্রহণ করেছি।
drdaeman

2

পূর্ববর্তী সমাধানগুলিতে আইপি ও নেট == নেট এ একটি বাগ রয়েছে। আইপি ও নেটমাস্ক = নেটটি সঠিক আইপি লুকআপ

বাগফিক্সড কোড:

import socket
import struct

def makeMask(n):
    "return a mask of n bits as a long integer"
    return (2L<<n-1) - 1

def dottedQuadToNum(ip):
    "convert decimal dotted quad string to long integer"
    return struct.unpack('L',socket.inet_aton(ip))[0]

def addressInNetwork(ip,net,netmask):
   "Is an address in a network"
   print "IP "+str(ip) + " NET "+str(net) + " MASK "+str(netmask)+" AND "+str(ip & netmask)
   return ip & netmask == net

def humannetcheck(ip,net):
        address=dottedQuadToNum(ip)
        netaddr=dottedQuadToNum(net.split("/")[0])
        netmask=makeMask(long(net.split("/")[1]))
        return addressInNetwork(address,netaddr,netmask)


print humannetcheck("192.168.0.1","192.168.0.0/24");
print humannetcheck("192.169.0.1","192.168.0.0/24");

2

চুজেন উত্তরের একটি বাগ রয়েছে।

নিম্নলিখিতটি সঠিক কোড:

def addressInNetwork(ip, net_n_bits):
   ipaddr = struct.unpack('<L', socket.inet_aton(ip))[0]
   net, bits = net_n_bits.split('/')
   netaddr = struct.unpack('<L', socket.inet_aton(net))[0]
   netmask = ((1L << int(bits)) - 1)
   return ipaddr & netmask == netaddr & netmask

দ্রষ্টব্য: ipaddr & netmask == netaddr & netmaskপরিবর্তে ipaddr & netmask == netmask

আমিও প্রতিস্থাপন ((2L<<int(bits)-1) - 1)সঙ্গে ((1L << int(bits)) - 1), আধুনিক আরো বোধগম্য মনে হয়।


আমি মনে করি মুখোশের রূপান্তরটি ((2L<<int(bits)-1) - 1)সঠিক। উদাহরণস্বরূপ যদি মুখোশটি 16 হয় তবে এটি "255.255.0.0" বা 65535L হওয়া উচিত তবে ((1L << int(bits)) - 1)32767L পাবেন যা সঠিক নয়।
ক্রিস.কিউ

@ ক্রিস.কিউ, ((1L << int(bits)) - 1)আমার সিস্টেমে 5৫৫৩৫ এল দেয়, সেটাকে ১ bits16 সেট করুন !!
দেবাংশু কুন্ডু

এছাড়াও, bitsসেট করার জন্য 0, ((2L<<int(bits)-1) - 1)ত্রুটি বাড়িয়ে তুলছে।
দেবাংশু কুন্ডু

হ্যাঁ, আসলে / 0, / 8, / 16, / 32 ব্যতীত অন্য কোনও মান সঠিকভাবে কাজ করছে না।
দেবাংশু কুন্ডু

2

আমি দীর্ঘতম উপসর্গের মিলের জন্য এখানে একটি ক্লাস লিখেছি:

#!/usr/bin/env python

class Node:
def __init__(self):
    self.left_child = None
    self.right_child = None
    self.data = "-"

def setData(self, data): self.data = data
def setLeft(self, pointer): self.left_child = pointer
def setRight(self, pointer): self.right_child = pointer
def getData(self): return self.data
def getLeft(self): return self.left_child
def getRight(self): return self.right_child

def __str__(self):
        return "LC: %s RC: %s data: %s" % (self.left_child, self.right_child, self.data)


class LPMTrie:      

def __init__(self):
    self.nodes = [Node()]
    self.curr_node_ind = 0

def addPrefix(self, prefix):
    self.curr_node_ind = 0
    prefix_bits = ''.join([bin(int(x)+256)[3:] for x in prefix.split('/')[0].split('.')])
    prefix_length = int(prefix.split('/')[1])
    for i in xrange(0, prefix_length):
        if (prefix_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setRight(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                tmp = Node()
                self.nodes[self.curr_node_ind].setLeft(len(self.nodes))
                tmp.setData(self.nodes[self.curr_node_ind].getData());
                self.curr_node_ind = len(self.nodes)
                self.nodes.append(tmp)

        if i == prefix_length - 1 :
            self.nodes[self.curr_node_ind].setData(prefix)

def searchPrefix(self, ip):
    self.curr_node_ind = 0
    ip_bits = ''.join([bin(int(x)+256)[3:] for x in ip.split('.')])
    for i in xrange(0, 32):
        if (ip_bits[i] == '1'):
            if (self.nodes[self.curr_node_ind].getRight()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getRight()
            else:
                return self.nodes[self.curr_node_ind].getData()
        else:
            if (self.nodes[self.curr_node_ind].getLeft()):
                self.curr_node_ind = self.nodes[self.curr_node_ind].getLeft()
            else:
                return self.nodes[self.curr_node_ind].getData()

    return None

def triePrint(self):
    n = 1
    for i in self.nodes:
        print n, ':'
        print i
        n += 1

এবং এখানে একটি পরীক্ষা প্রোগ্রাম:

n=LPMTrie()
n.addPrefix('10.25.63.0/24')
n.addPrefix('10.25.63.0/16')
n.addPrefix('100.25.63.2/8')
n.addPrefix('100.25.0.3/16')
print n.searchPrefix('10.25.63.152')
print n.searchPrefix('100.25.63.200')
#10.25.63.0/24
#100.25.0.3/16

1

আপনার স্ক্রিপ্ট জন্য আপনাকে ধন্যবাদ!
সবকিছুকে কাজ করার জন্য এটিতে আমার দীর্ঘ কাজ হয়েছে ... তাই আমি এটি এখানে ভাগ করছি

  • বাইনারি রূপান্তর ব্যবহারের চেয়ে নেটড্ডার ক্লাস ব্যবহার করা 10 গুণ ধীর গতির, সুতরাং আপনি যদি এটি আইপি-র একটি বৃহত তালিকায় ব্যবহার করতে চান তবে আপনার নেটড্রেড ক্লাস ব্যবহার না করার কথা বিবেচনা করা উচিত
  • মেকমাস্ক ফাংশনটি কাজ করছে না! শুধুমাত্র / 8, / 16, / 24
    প্রাক্তনের জন্য কাজ করছে :

    বিট = "21"; socket.inet_ntoa (স্ট্রাক্টপ্যাক ('= এল', (2 এল << ইনট (বিটস) -1) - 1)))
    '255.255.31.0' যেখানে এটি 255.255.248.0 হওয়া উচিত

    তাই আমি http://code.activestate.com/recips/576483-convert-subnetmask-from-cidr-notation-to-dotdecima/
    প্রাক্তন থেকে অন্য একটি ফাংশন ক্যালকডটনেটমাস্ক (মাস্ক) ব্যবহার করেছি :


#!/usr/bin/python
>>> calcDottedNetmask(21)
>>> '255.255.248.0'
  • আর একটি সমস্যা হ'ল ম্যাচের প্রক্রিয়াটি যদি কোনও আইপি কোনও নেটওয়ার্কের অন্তর্ভুক্ত থাকে! বেসিক অপারেশনটি তুলনা (আইপ্যাড্ডার এবং নেটমাস্ক) এবং (নেটওয়ার্ক এবং নেটমাস্ক) হওয়া উচিত।
    উদাঃ আপাতত ফাংশনটি ভুল

#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
>>>True which is completely WRONG!!

সুতরাং আমার নতুন ঠিকানাআইনেটওয়ার্ক ফাংশনটি দেখতে দেখতে দেখতে দেখতে:


#!/usr/bin/python
import socket,struct
def addressInNetwork(ip,net):
    '''This function allows you to check if on IP belogs to a Network'''
    ipaddr = struct.unpack('=L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netmask = struct.unpack('=L',socket.inet_aton(calcDottedNetmask(bits)))[0]
    network = struct.unpack('=L',socket.inet_aton(netaddr))[0] & netmask
    return (ipaddr & netmask) == (network & netmask)

def calcDottedNetmask(mask):
    bits = 0
    for i in xrange(32-int(mask),32):
        bits |= (1 > 24, (bits & 0xff0000) >> 16, (bits & 0xff00) >> 8 , (bits & 0xff))


এবং এখন, উত্তর ঠিক আছে !!


#!/usr/bin/python
>>> addressInNetwork('188.104.8.64','172.16.0.0/12')
False

আমি আশা করি এটি তাদের জন্য সময় সাশ্রয় করে অন্যান্য লোককে সহায়তা করবে!


4
উপরের কোডের বর্তমান সংস্করণটি সর্বশেষ লাইনে একটি ট্রেসব্যাক দেয় যা আপনি "| =" কোনও ইনট এবং একটি টিপল করতে পারেন।
শান রিফশনিডার

1

উপরের সমস্তটির সাথে সম্পর্কিত, আমার মনে হয় सॉকেট.ইন_এটন () নেটওয়ার্ক ক্রমে বাইটগুলি ফেরত দেয়, সুতরাং এগুলি আনপ্যাক করার সঠিক উপায় সম্ভবত

struct.unpack('!L', ... )

1
import socket,struct
def addressInNetwork(ip,net):
    "Is an address in a network"
    ipaddr = struct.unpack('!L',socket.inet_aton(ip))[0]
    netaddr,bits = net.split('/')
    netaddr = struct.unpack('!L',socket.inet_aton(netaddr))[0]
    netmask = ((1<<(32-int(bits))) - 1)^0xffffffff
    return ipaddr & netmask == netaddr & netmask
print addressInNetwork('10.10.10.110','10.10.10.128/25')
print addressInNetwork('10.10.10.110','10.10.10.0/25')
print addressInNetwork('10.10.10.110','10.20.10.128/25')

y পাইথন চেকসুবনেট.পিটি
মিথ্যা
সত্য
মিথ্যা


আপনি ইতিমধ্যে প্রদত্ত উত্তরগুলিতে কী যুক্ত করছেন তা ব্যাখ্যা করতে পারেন?
ডেভিড গায়ন

প্রদত্ত উত্তরের কিছু সমস্যা রয়েছে, যা সিআইডিআর পরিচালনা করতে পারেনি। আমি শুধু আইপি ঠিকানার বাইট ক্রম পরিবর্তন করেছি। ঠিক >>> struct.unpack('!L',socket.inet_aton('10.10.10.110'))[0] 168430190 >>> socket.inet_ntoa(struct.pack('!L', 168430190)) '10.10.10.110'
জনসন

4
উত্তর করার জন্য ধন্যবাদ. আমি অনুমান করি এটি স্পষ্ট করার জন্য আপনার উত্তরে আপনার যুক্ত করা উচিত। "কী" "কেন" এবং অবশেষে "কীভাবে" তা ব্যাখ্যা করার জন্য এটি স্ট্যাকওভারফ্লোতে রয়েছে। আপনার উত্তরে কেবল "কীভাবে" রয়েছে :( আমি আপনাকে সম্পাদনা করে আপনার উত্তরটি সম্পূর্ণ করতে দিই;)।
ডেভিড গায়ন

1

আমি স্ট্যান্ডার্ড লাইব্রেরিতে কোনও কিছুই জানি না, তবে পাইসুবনেট্রি একটি পাইথন লাইব্রেরি যা সাবনেট মিলবে।


লিঙ্কটি পরিবর্তন করা হয়েছে। পাইসুবনেট্রি গিটহাব
মায়াঙ্ক আগরওয়াল

0

উপরের বিভিন্ন উত্স থেকে এবং আমার নিজের গবেষণা থেকে, আমি এভাবেই কাজ করছিলাম সাবনেট এবং ঠিকানার গণনা। এই টুকরো প্রশ্ন এবং অন্যান্য সম্পর্কিত প্রশ্ন সমাধানের জন্য যথেষ্ট।

class iptools:
    @staticmethod
    def dottedQuadToNum(ip):
        "convert decimal dotted quad string to long integer"
        return struct.unpack('>L', socket.inet_aton(ip))[0]

    @staticmethod
    def numToDottedQuad(n):
        "convert long int to dotted quad string"
        return socket.inet_ntoa(struct.pack('>L', n))

    @staticmethod
    def makeNetmask(mask):
        bits = 0
        for i in xrange(32-int(mask), 32):
            bits |= (1 << i)
        return bits

    @staticmethod
    def ipToNetAndHost(ip, maskbits):
        "returns tuple (network, host) dotted-quad addresses given"
        " IP and mask size"
        # (by Greg Jorgensen)
        n = iptools.dottedQuadToNum(ip)
        m = iptools.makeMask(maskbits)
        net = n & m
        host = n - mask
        return iptools.numToDottedQuad(net), iptools.numToDottedQuad(host)

0

অজগরটিতে সাবনেট্রি নামে পরিচিত একটি এপিআই রয়েছে যা এই কাজটি খুব ভালভাবে করে। এটি একটি সাধারণ উদাহরণ:

import SubnetTree
t = SubnetTree.SubnetTree()
t.insert("10.0.1.3/32")
print("10.0.1.3" in t)

এই লিঙ্কটি


0

এখানে আমার কোড

# -*- coding: utf-8 -*-
import socket


class SubnetTest(object):
    def __init__(self, network):
        self.network, self.netmask = network.split('/')
        self._network_int = int(socket.inet_aton(self.network).encode('hex'), 16)
        self._mask = ((1L << int(self.netmask)) - 1) << (32 - int(self.netmask))
        self._net_prefix = self._network_int & self._mask

    def match(self, ip):
        '''
        判断传入的 IP 是不是本 Network 内的 IP
        '''
        ip_int = int(socket.inet_aton(ip).encode('hex'), 16)
        return (ip_int & self._mask) == self._net_prefix

st = SubnetTest('100.98.21.0/24')
print st.match('100.98.23.32')

0

আপনি যদি অন্য মডিউল আমদানি করতে না চান তবে আপনি যেতে পারেন:

def ip_matches_network(self, network, ip):
    """
    '{:08b}'.format(254): Converts 254 in a string of its binary representation

    ip_bits[:net_mask] == net_ip_bits[:net_mask]: compare the ip bit streams

    :param network: string like '192.168.33.0/24'
    :param ip: string like '192.168.33.1'
    :return: if ip matches network
    """
    net_ip, net_mask = network.split('/')
    net_mask = int(net_mask)
    ip_bits = ''.join('{:08b}'.format(int(x)) for x in ip.split('.'))
    net_ip_bits = ''.join('{:08b}'.format(int(x)) for x in net_ip.split('.'))
    # example: net_mask=24 -> compare strings at position 0 to 23
    return ip_bits[:net_mask] == net_ip_bits[:net_mask]

0

আমি এই উত্তরগুলিতে প্রস্তাবিত সমাধানগুলির একটি উপসেট চেষ্টা করেছি .. কোনও সাফল্য না পেয়ে অবশেষে আমি প্রস্তাবিত কোডটি অভিযোজিত এবং সংশোধন করে আমার স্থির ফাংশনটি লিখেছি।

আমি এটি পরীক্ষা করেছি এবং কমপক্ষে সামান্য এন্ডিয়ান আর্কিটেকচারে কাজ করি - উদাহরণস্বরূপ - কেউ যদি কোনও বড় এন্ডিয়ান আর্কিটেকচার চেষ্টা করতে চান তবে দয়া করে আমাকে প্রতিক্রিয়া জানান।

IP2Intকোড এই পোস্ট থেকে আসে , অন্য পদ্ধতিটি সম্পূর্ণরূপে (আমার পরীক্ষার ক্ষেত্রে) এই প্রশ্নের পূর্ববর্তী প্রস্তাবগুলির কার্যকারিতা স্থির fix

কোড:

def IP2Int(ip):
    o = map(int, ip.split('.'))
    res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
    return res


def addressInNetwork(ip, net_n_bits):
    ipaddr = IP2Int(ip)
    net, bits = net_n_bits.split('/')
    netaddr = IP2Int(net)
    bits_num = int(bits)
    netmask = ((1L << bits_num) - 1) << (32 - bits_num)
    return ipaddr & netmask == netaddr & netmask

আশা করি দরকারী,


0

নেটড্ডার প্যাকেজটি ব্যবহার করে সমাধানটি এখানে দেওয়া হল

from netaddr import IPNetwork, IPAddress


def network_has_ip(network, ip):

    if not isinstance(network, IPNetwork):
        raise Exception("network parameter must be {0} instance".format(IPNetwork.__name__))

    if not isinstance(ip, IPAddress):
        raise Exception("ip parameter must be {0} instance".format(IPAddress.__name__))

    return (network.cidr.ip.value & network.netmask.value) == (ip.value & network.netmask.value)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.