আমি কীভাবে জাঙ্গোতে আইপি ঠিকানা পাব?


287

কীভাবে আমি জাঙ্গোতে ব্যবহারকারীর আইপি পেতে পারি?

আমার মতামত আছে:

# Create your views
from django.contrib.gis.utils import GeoIP
from django.template import  RequestContext
from django.shortcuts import render_to_response


def home(request):
  g = GeoIP()
  client_ip = request.META['REMOTE_ADDR']
  lat,long = g.lat_lon(client_ip)
  return render_to_response('home_page_tmp.html',locals())

তবে আমি এই ত্রুটিটি পেয়েছি:

KeyError at /mypage/
    'REMOTE_ADDR'
    Request Method: GET
    Request URL:    http://mywebsite.com/mypage/
    Django Version: 1.2.4
    Exception Type: KeyError
    Exception Value:    
    'REMOTE_ADDR'
    Exception Location: /mysite/homepage/views.py in home, line 9
    Python Executable:  /usr/bin/python
    Python Version: 2.6.6
    Python Path:    ['/mysite', '/usr/local/lib/python2.6/dist-packages/flup-1.0.2-py2.6.egg', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload', '/usr/local/lib/python2.6/dist-packages', '/usr/lib/python2.6/dist-packages', '/usr/lib/pymodules/python2.6']
    Server time:    Sun, 2 Jan 2011 20:42:50 -0600

2
ডাম্পিংয়ের অনুরোধ করে দেখুন
Mমেটা.কিজ

2
['HTTP_COOKIE', 'SQLT_NAME', 'REQUEST_METHOD', 'PATH_INFO', 'SERVER_PROTOCOL', 'QUERY_STRING', 'CONTENT_LENGTH', 'HTTP_ACCEPT_CHARSET', 'HTTP_USER_AG' ', HTTP_, এসটিএইচটিসি_আর , 'SERVER_PORT', 'wsgi.input', 'HTTP_HOST', 'wsgi.multithread', 'HTTP_CACHE_CONTROL', 'HTTP_ACCEPT', 'wsgi.version', 'wsgi.run_once', 'wsgi.er متاثر'। মাল্টিপ্রসেস ',' HTTP_ACCEPT_LANGUAGE ',' CONTENT_TYPE ',' CSRF_COOKIE ',' HTTP_ACCEPT_ENCODING ']
অবতার

2
এই দুর্দান্ত প্রশ্নের জন্য আপনাকে ধন্যবাদ। আমার ফাস্টসিজি REMOTE_ADDR মেটা কীটি পাস করছিল না। আমি nginx.conf এ নীচের লাইনটি যুক্ত করেছি এবং সমস্যাটি সমাধান করেছি: ফাস্টcgi_param REMOTE_ADDR $ রিমোট_এডিডিআর;
অবতার 15

উত্তর:


434
def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

নিশ্চিত হয়ে নিন যে আপনার বিপরীত প্রক্সি (যদি থাকে) সঠিকভাবে কনফিগার করা আছে (উদাঃ) mod_rpaf অ্যাপাচি-এর জন্য ইনস্টল করা)।

দ্রষ্টব্য: উপরেরগুলি প্রথম আইটেমটি এতে ব্যবহার করে X-Forwarded-Forতবে আপনি সর্বশেষ আইটেমটি ব্যবহার করতে চাইতে পারেন (উদাহরণস্বরূপ, হেরোকুর ক্ষেত্রে: হেরোকুতে ক্লায়েন্টের আসল আইপি ঠিকানা পান )

এবং তারপরে কেবল এটির যুক্তি হিসাবে অনুরোধটি পাস করুন;

get_client_ip(request)

8
ip = get_client_ip(request)আপনার দর্শন ফাংশন কল ।
ইয়াঞ্চেঙ্কো

4
আসল ক্লায়েন্টের আইপি ঠিকানাটি প্রথম নয় তবে HTTP_X_FORWARDED_FOR এ শেষ (উইকিপিডিয়া পৃষ্ঠাটি দেখুন)
জুলাই

5
@ জজুল এটি সঠিক নয়। ফর্ম্যাটটি সাধারণত হয় X-Forwarded-For: client, proxy1, proxy2। সুতরাং প্রথম ঠিকানাটি ক্লায়েন্টের।
মাইকেল জলপ্রপাত

51
এই কাজটি বিপজ্জনক। অনেকগুলি সেটআপের মাধ্যমে একটি দূষিত ব্যবহারকারী সহজেই এই ফাংশনটি তাদের যে কোনও ঠিকানা (তাদের আসল পরিবর্তে) ফেরত দিতে পারে। Esd.io/blog/flask-apps-heroku-real-ip-spoofing.html
এলি

8
জ্যাঙ্গো ডক্স থেকে ( "REMOTE_ADDR বা অনুরূপ মান উপর নির্ভর ব্যাপকভাবে একটি খারাপ অভ্যাস হিসেবে পরিচিত" djangoproject.com/weblog/2009/jul/28/security/#secondary-issue )
Zags

209

আপনি ব্যবহার করতে পারেন জ্যাঙ্গো-ipware যা পাইথন সমর্থন 2 & 3 এবং হ্যান্ডলগুলি IPv4- র & IPv6,

ইনস্টল করুন:

pip install django-ipware

সাধারণ ব্যবহার:

# In a view or a middleware where the `request` object is available

from ipware import get_client_ip
ip, is_routable = get_client_ip(request)
if ip is None:
    # Unable to get the client's IP address
else:
    # We got the client's IP address
    if is_routable:
        # The client's IP address is publicly routable on the Internet
    else:
        # The client's IP address is private

# Order of precedence is (Public, Private, Loopback, None)

উন্নত ব্যবহার:

  • কাস্টম শিরোলেখ - আইপওয়্যারটি দেখার জন্য কাস্টম অনুরোধ শিরোনাম:

    i, r = get_client_ip(request, request_header_order=['X_FORWARDED_FOR'])
    i, r = get_client_ip(request, request_header_order=['X_FORWARDED_FOR', 'REMOTE_ADDR'])
  • প্রক্সি গণনা - একটি নির্দিষ্ট সংখ্যক প্রক্সি পিছনে জ্যাঙ্গো সার্ভার রয়েছে:

    i, r = get_client_ip(request, proxy_count=1)
  • বিশ্বস্ত প্রক্সি - জাজানো সার্ভার এক বা একাধিক পরিচিত এবং বিশ্বস্ত প্রক্সিগুলির পিছনে রয়েছে:

    i, r = get_client_ip(request, proxy_trusted_ips=('177.2.2.2'))
    
    # For multiple proxies, simply add them to the list
    i, r = get_client_ip(request, proxy_trusted_ips=('177.2.2.2', '177.3.3.3'))
    
    # For proxies with fixed sub-domain and dynamic IP addresses, use partial pattern
    i, r = get_client_ip(request, proxy_trusted_ips=('177.2.', '177.3.'))

দ্রষ্টব্য: এই বিজ্ঞপ্তিটি পড়ুন


17
এর উত্স কোডটি একবার দেখুন। এটি এখানে অন্যান্য উত্তর দ্বারা চিহ্নিত সমস্ত জটিলতা পরিচালনা করে।
হোস্টেডমেট্রিক্স ডটকম

5
থেক্সএক্স @ হেলিওডর - হ্যাঁ, আমি গড় ব্যবহারের ক্ষেত্রে মডিউলটিকে খুব সহজ এবং জটিল ব্যবহারের ক্ষেত্রে খুব নমনীয় করে তুলেছি। ন্যূনতমভাবে, আপনি নিজের ঘূর্ণায়মানের আগে এর গিথব পৃষ্ঠাটি দেখতে চান।
un33k

3
দ্রষ্টব্য যে জাঙ্গো-আইপওয়ারের সেটিংস ডিফল্টরূপে সুরক্ষিত নয়! অন্য যে কোনও একটি ভেরিয়েবল পাস করতে পারবেন এবং আপনার সাইট সেই আইপি লগ করবে। IPWARE_META_PRECEDENCE_LISTআপনি যে ভেরিয়েবলটি ব্যবহার করেন তা সর্বদা সেট করুন বা pypi.python.org/pypi/WsgiUnproxy- এর
vdboor

@vdboor আপনি কি আরও কিছুটা ব্যাখ্যা করতে পারবেন? আমি রেপোতে আইপিওয়ার্লিমেটেপ্রেসিএডিপিআরসিইডিএনসিসিআইপিআইআইএল খুঁজে পাচ্ছি না।
মনোলিথ

2
@ থাজে দয়া করে নোট করুন যে ২.০.০ পর্যন্ত আপনার ব্যবহার করা উচিত get_client_ip()get_real_ipঅবচয় করা হয়েছে এবং 3.0 এ সরানো হবে।
un33k

77

আলেকজান্ডারের উত্তর দুর্দান্ত, তবে প্রক্সিগুলির হ্যান্ডলিংয়ের অভাব রয়েছে যা কখনও কখনও HTTP_X_FORWARDED_FOR শিরোনামে একাধিক আইপি দেয়।

আসল আইপিটি সাধারণত তালিকাটির শেষে থাকে, এখানে বর্ণিত হিসাবে: http://en.wikedia.org/wiki/X- ফরওয়ার্ড- ফর

সমাধানটি আলেকজান্ডারের কোডের একটি সাধারণ পরিবর্তন:

def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[-1].strip()
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip

5
হ্যাঁ, আইপি তালিকার শুরুতে । এটি এখানে ভুল।
পাইকলার

4
প্রকৃতপক্ষে, ব্যবহারকারী যদি প্রক্সিটির পিছনে থাকে তবে আপনি ব্যবহারকারীর অভ্যন্তরীণ আইপি ঠিকানাটি পেতে পারেন, অর্থাত্ একটি আরএফসি 1918 ঠিকানা। বেশিরভাগ ক্ষেত্রে, এটি মোটেই খুব কাম্য নয়। এই সমাধানটি ক্লায়েন্টের বাহ্যিক আইপি ঠিকানা (প্রক্সি ঠিকানা) পাওয়ার দিকে মনোনিবেশ করে, যা ডান-সর্বাধিক ঠিকানা।
সাভার

2
ধন্যবাদ. সাধারণত আমি যখন আমি কীগুলির জন্য অনুরোধ করি তখন আমি request.METAএকটি ডিফল্ট মান অন্তর্ভুক্ত করি যেহেতু শিরোনামগুলি প্রায়শই মাইজ করে থাকে:request.META.get('REMOTE_ADDR', None)
কার্ল জি

2
@ কার্লজি আপনার কোডটি আরও স্বচ্ছ, তবে প্রাপ্তির পদ্ধতিটি উত্তরাধিকার সূত্রে django.utils.datastructures. মাল্টিভ্যালিউডিক্ট এবং ডিফল্ট মানটি কোনওটি নয়। তবে আপনি অবশ্যই এটি কোনওটি ছাড়া অন্য কিছু হতে চাইলে অবশ্যই একটি ডিফল্ট মান অন্তর্ভুক্ত করা অবশ্যই বোধগম্য।
সাভার

2
আপনি যদি এক্স-ফরওয়ার্ড-ফর স্ক্র্যাব না করেন তবে যদি অনুরোধগুলি আপনার প্রথম সার্ভারে আঘাত করে, তবে সেই তালিকার প্রথম মানটি ব্যবহারকারী সরবরাহ করা হবে । একটি দূষিত ব্যবহারকারী সহজেই তাদের যে কোনও আইপি ঠিকানা ছদ্মবেশে ফেলতে পারে। আপনি যে ঠিকানাটি চান তা হ'ল আপনার যে কোনও সার্ভারের আগে প্রথম আইপি, তালিকার প্রথমটি নয়।
এলি

12

আমি ইয়াঞ্চেঙ্কোর উত্তরের উন্নতির পরামর্শ দিতে চাই।

X_FORWARDED_FOR তালিকায় প্রথম আইপি নেওয়ার পরিবর্তে, আমি প্রথমটি গ্রহণ করি যা একটি পরিচিত অভ্যন্তরীণ আইপি হিসাবে নয়, কারণ কিছু রাউটার প্রোটোকলকে সম্মান করে না, এবং আপনি তালিকার প্রথম মান হিসাবে অভ্যন্তরীণ আইপিএস দেখতে পাচ্ছেন।

PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', )

def get_client_ip(request):
    """get the client ip from the request
    """
    remote_address = request.META.get('REMOTE_ADDR')
    # set the default value of the ip to be the REMOTE_ADDR if available
    # else None
    ip = remote_address
    # try to get the first non-proxy ip (not a private ip) from the
    # HTTP_X_FORWARDED_FOR
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        proxies = x_forwarded_for.split(',')
        # remove the private ips from the beginning
        while (len(proxies) > 0 and
                proxies[0].startswith(PRIVATE_IPS_PREFIX)):
            proxies.pop(0)
        # take the first ip which is not a private one (of a proxy)
        if len(proxies) > 0:
            ip = proxies[0]

    return ip

আমি আশা করি এটি একই সমস্যাযুক্ত সহযোদ্ধা গুগলদের সহায়তা করবে।


এই কোড চেক নয় যে REMOTE_ADDR থেকে আইপি ব্যক্তিগত HTTP_X_FORWARDED_FOR ক্ষেত্রটিতে চেক সামনে, যেমন এটি সম্ভবত উচিত (আরো বলেছেনঃ '' 127.0.0.1 'বা' 127. 'সম্ভবত IPv6, সমতুল সঙ্গে একসঙ্গে, PRIVATE_IPS_PREFIX থাকা উচিত।
Rasmus Kaj

1
প্রযুক্তিগতভাবে, এই উপসর্গগুলি (172, 192) অগত্যা ব্যক্তিগত ঠিকানা বোঝায় না।
maniexx

2
ব্যক্তিগত নেটওয়ার্কগুলির জন্য নির্ধারিত ঠিকানা ব্যাপ্তিগুলি হ'ল: 172.16.0.0–172.31.255.255 (16 "বর্গ বি" নেটওয়ার্ক), 192.168.0.0–192.168.255.255 (1 "শ্রেণি বি" নেটওয়ার্ক) এবং 10.0.0.0–10.255.255.255 (1 "ক্লাস এ" বা 256 "ক্লাস বি" নেটওয়ার্ক)।
tzot

is_ अवैध_ip সংজ্ঞায়িত করা হয়নি
প্রসেনজিৎ

7

এটি সম্পাদন করার জন্য এখানে একটি সংক্ষিপ্ত ওয়ান লাইনার:

request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR', '')).split(',')[0].strip()

3
যদি উভয়ই আর কেউ না ফেরায় তবে আপনি একটি ত্রুটি পাবেন।
গৌরব চাওলা

1
ঝরঝরে কিন্তু খুব পঠনযোগ্য নয়
খরগোশ.আরন

6

সবচেয়ে সহজ সমাধান (আপনি যদি ফাস্টসিজি + নিগেক্স ব্যবহার করছেন) এটি ইগোরিলা মন্তব্য করেছে:

এই দুর্দান্ত প্রশ্নের জন্য আপনাকে ধন্যবাদ। আমার ফাস্টসিজি REMOTE_ADDR মেটা কীটি পাস করছিল না। আমি nginx.conf এ নীচের লাইনটি যুক্ত করেছি এবং সমস্যাটি সমাধান করেছি: ফাস্টcgi_param REMOTE_ADDR $ রিমোট_এডিডিআর; - itgorilla

PS: আমি তার উত্তরটি আরও দৃশ্যমান করার জন্য এই উত্তরটি যুক্ত করেছি।


1
এনজিনেক্স (বিপরীত প্রক্সি) এবং গানিকর্নের জন্য তুলনামূলক সমাধান কী? proxy_set_header REMOTE_ADDR $remote_addr;nginx.conf এ যুক্ত হলে সমস্যা উপশম হয় না।
হাসান বৈগ

6

আর কোনও বিভ্রান্তি নেই জাজানোর সাম্প্রতিক সংস্করণগুলিতে ক্লায়েন্টের আইপি ঠিকানা পাওয়া যায় তা স্পষ্টভাবে উল্লেখ করা হয়েছে

request.META.get("REMOTE_ADDR")

আরও তথ্যের জন্য জ্যাঙ্গো ডক্স পরীক্ষা করে দেখুন


কিছু সময় বাঁচিয়েছি, ধন্যবাদ !!
hadooper

5

আমার ক্ষেত্রে উপরের কোনওটিই কাজ করে না, সুতরাং আমাকে uwsgi+ পরীক্ষা করতে হবেdjango উত্স কোড হবে এবং এনজিনেক্সে স্ট্যাটিক প্যারাম পাস করতে হবে এবং কেন / কীভাবে এবং নীচে আমি যা পেয়েছি তা দেখতে হবে।

এনভ তথ্য:
অজগর সংস্করণ: 2.7.5
জ্যাঙ্গো (1, 6, 6, 'final', 0)
সংস্করণ: nginx/1.6.0
এনগিনেক্স সংস্করণ: উউজি:2.0.7

এনভের সেটিংয়ের তথ্য: এনগিনেক্স আপস্ট্রিম ইউনিক্স সকেট হিসাবে
পোর্ট 80উউসগিতে বিপরীত প্রক্সি শোনার হিসাবে, অনুরোধটির অবশেষে প্রতিক্রিয়া জানাবে

জ্যাঙ্গো কনফিগারেশন তথ্য:

USE_X_FORWARDED_HOST = True # with or without this line does not matter

nginx কনফিগারেশন:

uwsgi_param      X-Real-IP              $remote_addr;
// uwsgi_param   X-Forwarded-For        $proxy_add_x_forwarded_for;
// uwsgi_param   HTTP_X_FORWARDED_FOR   $proxy_add_x_forwarded_for;

// hardcode for testing
uwsgi_param      X-Forwarded-For        "10.10.10.10";
uwsgi_param      HTTP_X_FORWARDED_FOR   "20.20.20.20";

জ্যাঙ্গো অ্যাপ্লিকেশনে সমস্ত প্যারামগুলি পেয়েছি:

X-Forwarded-For :       10.10.10.10
HTTP_X_FORWARDED_FOR :  20.20.20.20

উপসংহার:

সুতরাং মূলত, আপনাকে ঠিক একই ক্ষেত্র / প্যারাম নামটি এনজিএনএক্সে নির্দিষ্ট করতে হবে এবং ব্যবহার করতে হবে request.META[field/param] জ্যাঙ্গো অ্যাপ্লিকেশনটিতে ।

এবং এখন আপনি সিদ্ধান্ত নিতে পারেন কোনও মিডলওয়্যার (ইন্টারসেপ্টর) যুক্ত করবেন বা HTTP_X_FORWARDED_FORনির্দিষ্ট দৃশ্যে কেবল পার্স করবেন কিনা ।


2

মূলত জ্যাঙ্গো থেকে কার্যকারিতা অপসারণের কারণটি হ'ল চূড়ান্তভাবে বিশ্বাস করা যায় না। কারণ হ'ল এটি ছলচাতুরী করা সহজ। উদাহরণস্বরূপ, একটি এনজিনেক্স বিপরীত প্রক্সি কনফিগার করার প্রস্তাবিত উপায় হ'ল:

add_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Real-Ip       $remote_addr;

যখন তুমি কর:

curl -H 'X-Forwarded-For: 8.8.8.8, 192.168.1.2' http://192.168.1.3/

Myhost.com এ আপনার nginx এর পরে প্রেরণ করবে:

X-Forwarded-For: 8.8.8.8, 192.168.1.2, 192.168.1.3

দ্য X-Real-IPযদি আপনি নির্দেশাবলী অন্ধ অনুসরণ প্রথম পূর্ববর্তী প্রক্সির আইপি হবে।

আপনার ব্যবহারকারীরা কে ইস্যু তা বিশ্বাস করার ক্ষেত্রে আপনি এই জাতীয় কিছু চেষ্টা করতে পারেন django-xff: https://pypi.python.org/pypi/django-xff/


1

আমি উপরের উত্তরে প্রক্সিও হারিয়েছিলাম। আমি জাঙ্গো_সি_সামান্য_মোজনget_ip_address_from_request থেকে ব্যবহার করেছি

from easy_timezones.utils import get_ip_address_from_request, is_valid_ip, is_local_ip
ip = get_ip_address_from_request(request)
try:
    if is_valid_ip(ip):
        geoip_record = IpRange.objects.by_ip(ip)
except IpRange.DoesNotExist:
    return None

এবং এখানে পদ্ধতি get_ip_address_from_request, আইপিভি 4 এবং আইপিভি 6 প্রস্তুত রয়েছে:

def get_ip_address_from_request(request):
    """ Makes the best attempt to get the client's real IP or return the loopback """
    PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', '127.')
    ip_address = ''
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '')
    if x_forwarded_for and ',' not in x_forwarded_for:
        if not x_forwarded_for.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_forwarded_for):
            ip_address = x_forwarded_for.strip()
    else:
        ips = [ip.strip() for ip in x_forwarded_for.split(',')]
        for ip in ips:
            if ip.startswith(PRIVATE_IPS_PREFIX):
                continue
            elif not is_valid_ip(ip):
                continue
            else:
                ip_address = ip
                break
    if not ip_address:
        x_real_ip = request.META.get('HTTP_X_REAL_IP', '')
        if x_real_ip:
            if not x_real_ip.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_real_ip):
                ip_address = x_real_ip.strip()
    if not ip_address:
        remote_addr = request.META.get('REMOTE_ADDR', '')
        if remote_addr:
            if not remote_addr.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(remote_addr):
                ip_address = remote_addr.strip()
    if not ip_address:
        ip_address = '127.0.0.1'
    return ip_address

0

Django.VERSION এ (2, 1, 1, 'চূড়ান্ত', 0) অনুরোধ হ্যান্ডলার

sock=request._stream.stream.raw._sock
#<socket.socket fd=1236, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.111', 8000), raddr=('192.168.1.111', 64725)>
client_ip,port=sock.getpeername()

আপনি যদি উপরের কোডটি দু'বার কল করেন তবে আপনি পেয়েছেন

অ্যাট্রিবিউটআরার ("'_ io.BytesIO' অবজেক্টের 'স্ট্রিম'" এর কোনও বৈশিষ্ট্য নেই)

অ্যাট্রিবিউটআরার ("'লিমিটেড স্ট্রিম' অবজেক্টের কোনও 'কাঁচা'" নেই)

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