Merge pull request #4625 from fmyzjs/ipv6
Support ipv6 in geoinfo and Embargo
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -169,3 +169,4 @@ Clinton Blackburn <cblackburn@edx.org>
|
||||
Dennis Jen <djen@edx.org>
|
||||
Filippo Valsorda <hi@filippo.io>
|
||||
Ivica Ceraj <ceraj@mit.edu>
|
||||
Jason Zhu <fmyzjs@gmail.com>
|
||||
@@ -129,7 +129,7 @@ sys.path.append(COMMON_ROOT / 'lib')
|
||||
|
||||
# For geolocation ip database
|
||||
GEOIP_PATH = REPO_ROOT / "common/static/data/geoip/GeoIP.dat"
|
||||
|
||||
GEOIPV6_PATH = REPO_ROOT / "common/static/data/geoip/GeoIPv6.dat"
|
||||
|
||||
############################# WEB CONFIGURATION #############################
|
||||
# This is where we stick our compiled template files.
|
||||
|
||||
@@ -86,13 +86,17 @@ class EmbargoMiddleware(object):
|
||||
(ip_addr, course_id)
|
||||
else:
|
||||
msg = "Embargo: Restricting IP address %s because IP is blacklisted." % ip_addr
|
||||
|
||||
log.info(msg)
|
||||
return response
|
||||
# ipv6 support
|
||||
if ip_addr.find(':') >= 0:
|
||||
country_code_from_ip = pygeoip.GeoIP(settings.GEOIPV6_PATH).country_code_by_addr(ip_addr)
|
||||
else:
|
||||
country_code_from_ip = pygeoip.GeoIP(settings.GEOIP_PATH).country_code_by_addr(ip_addr)
|
||||
|
||||
country_code_from_ip = pygeoip.GeoIP(settings.GEOIP_PATH).country_code_by_addr(ip_addr)
|
||||
is_embargoed = country_code_from_ip in EmbargoedState.current().embargoed_countries_list
|
||||
# Fail if country is embargoed and the ip address isn't explicitly whitelisted
|
||||
# Fail if country is embargoed and the ip address isn't explicitly
|
||||
# whitelisted
|
||||
if is_embargoed and ip_addr not in IPFilter.current().whitelist_ips:
|
||||
if course_is_embargoed:
|
||||
msg = "Embargo: Restricting IP address %s to course %s because IP is from country %s." % \
|
||||
|
||||
@@ -64,6 +64,8 @@ class EmbargoMiddlewareTests(TestCase):
|
||||
'3.0.0.0': 'SY',
|
||||
'4.0.0.0': 'SD',
|
||||
'5.0.0.0': 'AQ', # Antartica
|
||||
'2001:250::': 'CN',
|
||||
'2001:1340::': 'CU',
|
||||
}
|
||||
return ip_dict.get(ip_addr, 'US')
|
||||
|
||||
@@ -93,6 +95,32 @@ class EmbargoMiddlewareTests(TestCase):
|
||||
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='5.0.0.0', REMOTE_ADDR='5.0.0.0')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_countries_ipv6(self):
|
||||
# Accessing an embargoed page from a blocked IP should cause a redirect
|
||||
response = self.client.get(self.embargoed_page, HTTP_X_FORWARDED_FOR='2001:1340::', REMOTE_ADDR='2001:1340::')
|
||||
self.assertEqual(response.status_code, 302)
|
||||
# Following the redirect should give us the embargo page
|
||||
response = self.client.get(
|
||||
self.embargoed_page,
|
||||
HTTP_X_FORWARDED_FOR='2001:1340::',
|
||||
REMOTE_ADDR='2001:1340::',
|
||||
follow=True
|
||||
)
|
||||
self.assertIn(self.embargo_text, response.content)
|
||||
|
||||
# Accessing a regular page from a blocked IP should succeed
|
||||
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='2001:1340::', REMOTE_ADDR='2001:1340::')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Accessing an embargoed page from a non-embargoed IP should succeed
|
||||
response = self.client.get(self.embargoed_page, HTTP_X_FORWARDED_FOR='2001:250::', REMOTE_ADDR='2001:250::')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
# Accessing a regular page from a non-embargoed IP should succeed
|
||||
response = self.client.get(self.regular_page, HTTP_X_FORWARDED_FOR='2001:250::', REMOTE_ADDR='2001:250::')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||
def test_ip_exceptions(self):
|
||||
# Explicitly whitelist/blacklist some IPs
|
||||
|
||||
@@ -36,7 +36,10 @@ class CountryMiddleware(object):
|
||||
del request.session['ip_address']
|
||||
del request.session['country_code']
|
||||
elif new_ip_address != old_ip_address:
|
||||
country_code = pygeoip.GeoIP(settings.GEOIP_PATH).country_code_by_addr(new_ip_address)
|
||||
if new_ip_address.find(':') >= 0:
|
||||
country_code = pygeoip.GeoIP(settings.GEOIPV6_PATH).country_code_by_addr(new_ip_address)
|
||||
else:
|
||||
country_code = pygeoip.GeoIP(settings.GEOIP_PATH).country_code_by_addr(new_ip_address)
|
||||
request.session['country_code'] = country_code
|
||||
request.session['ip_address'] = new_ip_address
|
||||
log.debug('Country code for IP: %s is set to %s', new_ip_address, country_code)
|
||||
|
||||
@@ -41,6 +41,7 @@ class CountryMiddlewareTests(TestCase):
|
||||
'117.79.83.1': 'CN',
|
||||
'117.79.83.100': 'CN',
|
||||
'4.0.0.0': 'SD',
|
||||
'2001:da8:20f:1502:edcf:550b:4a9c:207d': 'CN',
|
||||
}
|
||||
return ip_dict.get(ip_addr, 'US')
|
||||
|
||||
@@ -106,3 +107,19 @@ class CountryMiddlewareTests(TestCase):
|
||||
# No country code exists after request processing.
|
||||
self.assertNotIn('country_code', request.session)
|
||||
self.assertNotIn('ip_address', request.session)
|
||||
|
||||
def test_ip_address_is_ipv6(self):
|
||||
request = self.request_factory.get(
|
||||
'/somewhere',
|
||||
HTTP_X_FORWARDED_FOR='2001:da8:20f:1502:edcf:550b:4a9c:207d'
|
||||
)
|
||||
request.user = self.authenticated_user
|
||||
self.session_middleware.process_request(request)
|
||||
# No country code exists before request.
|
||||
self.assertNotIn('country_code', request.session)
|
||||
self.assertNotIn('ip_address', request.session)
|
||||
self.country_middleware.process_request(request)
|
||||
# Country code added to session.
|
||||
self.assertEqual('CN', request.session.get('country_code'))
|
||||
self.assertEqual(
|
||||
'2001:da8:20f:1502:edcf:550b:4a9c:207d', request.session.get('ip_address'))
|
||||
|
||||
BIN
common/static/data/geoip/GeoIPv6.dat
Normal file
BIN
common/static/data/geoip/GeoIPv6.dat
Normal file
Binary file not shown.
@@ -307,7 +307,7 @@ NODE_PATH = ':'.join(node_paths)
|
||||
|
||||
# For geolocation ip database
|
||||
GEOIP_PATH = REPO_ROOT / "common/static/data/geoip/GeoIP.dat"
|
||||
|
||||
GEOIPV6_PATH = REPO_ROOT / "common/static/data/geoip/GeoIPv6.dat"
|
||||
|
||||
# Where to look for a status message
|
||||
STATUS_MESSAGE_PATH = ENV_ROOT / "status_message.json"
|
||||
|
||||
Reference in New Issue
Block a user