2009-10-26 16 views
9

Vì vậy, tôi có một thiết lập đơn giản với nginx cho phương tiện truyền thông tĩnh và cân bằng tải và lốc xoáy như máy chủ web cho django (4 máy chủ đang chạy). Vấn đề của tôi là REMOTE_ADDR không nhận được thông qua vào django vì vậy tôi nhận được một KeyError:REMOTE_ADDR không nhận được gửi đến Django sử dụng nginx & tornado

article.ip = request.META['REMOTE_ADDR']

Địa chỉ từ xa là nhận được gửi qua như nhờ vào sự nginx.conf X-Real-IP (HTTP_X_REAL_IP):

location/{ 
     proxy_pass_header Server; 
     proxy_set_header Host $http_host; 
     proxy_redirect false; 
     proxy_set_header X-Real-IP $remote_addr; 
     proxy_set_header X-Scheme $scheme; 
     proxy_pass http://frontends; 
    } 

Vì HTTP được thêm vào khóa META Tôi không thể chỉ thực hiện proxy_set_header remote_addr $ remote_addr. Những gì tôi có thể làm là đọc X-Real-IP nếu không tìm thấy khóa addr từ xa nhưng tôi tò mò nếu có giải pháp thông minh hơn.

Cảm ơn!

+0

Không có giải pháp đúng, nhưng tôi đã thêm một middleware django mà quay HTTP_X_REAL_IP vào REMOTE_ADDR. – Nixarn

+0

Các báo cáo này sẽ giúp bạn: proxy_redirect off; proxy_set_header X-Real-IP $ remote_addr; \t \t proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for; \t \t proxy_set_header X-Đề án $ scheme; – glarrain

Trả lời

11

Hãy thử điều này một:

location/{ 
    proxy_pass http://frontends; 
    proxy_pass_header Server; 
    proxy_redirect off; 
    proxy_set_header Host $http_host; 
    proxy_set_header X-Real-IP $remote_addr; 
    proxy_set_header X-Scheme $scheme; 
    proxy_set_header REMOTE_ADDR $remote_addr; 
} 

Chỉ cần thêm proxy_set_header REMOTE_ADDR và nó phải làm việc tốt.

thử với:

  • Django 1.5.4
  • Nginx 1.4.3
  • Tornado 2.2.1
+0

theo này: https: //easyengine.io/tutorials/nginx/forwarding-visitors-real-ip/ bên trong backend-nginx conf: vị trí ~ \ .php $ { fastcgi_param REMOTE_ADDR $ http_x_real_ip; # ... các quy tắc khác } – Amini

5

Tôi có thiết lập tương tự. Sau khi đặt nginx trước apache, tôi nhận thấy rằng IP trong nhật ký apache luôn là 127.0.0.1. Cài đặt "libapache2-mod-rpaf" dường như sửa chữa nó. Tôi không có ý tưởng nếu vấn đề của bạn có liên quan.

+0

Ah cảm ơn, nhưng tôi không sử dụng apache ở tất cả cho dự án này. – Nixarn

+0

oops, tất nhiên, xin lỗi về điều đó – asciitaxi

+0

Cảm ơn câu trả lời của bạn. BTW: Điều này cũng giúp phần mềm PHP, dựa trên $ _SERVER ['REMOTE_ADDR'] mà bây giờ có chứa IP từ xa thực sự là tốt. – Leif

0

Không, đó là not possible để chuyển sang remote_addr. Vì vậy, giải pháp duy nhất mà tôi biết là sử dụng X-Real-IP hoặc X-Forwarded-For và đảm bảo rằng chương trình phụ trợ xử lý đúng.

Edit: này áp dụng đối với fastcgi_pass, không thường xuyên nginx proxy_pass

+0

Không thể? @ Juande của giải pháp hoạt động khá tốt cho tôi. –

+0

Để xử lý fastcgi, vâng. Nhưng câu hỏi là về một proxy nginx. – windyjonas

+1

Rất tiếc, tôi nên đọc kỹ hơn - 'proxy_pass' không phải là 'fastcgi_pass'. Tôi không thể bãi bỏ nhược điểm của tôi trừ khi bạn chỉnh sửa câu trả lời của mình. :/Nếu bạn đã chỉnh sửa nó, tôi sẽ vui lòng upvote thay vào đó. –

14

Đây là cách tôi giải quyết được vấn đề. Bằng cách sử dụng phần mềm trung gian này:

class SetRemoteAddrMiddleware(object): 
    def process_request(self, request): 
     if not request.META.has_key('REMOTE_ADDR'): 
      try: 
       request.META['REMOTE_ADDR'] = request.META['HTTP_X_REAL_IP'] 
      except: 
       request.META['REMOTE_ADDR'] = '1.1.1.1' # This will place a valid IP in REMOTE_ADDR but this shouldn't happen 

Hy vọng điều đó sẽ hữu ích!

+2

Chỉ có vấn đề với điều này là nếu bạn âm thầm thả các lỗi, bạn sẽ phát hiện ra rằng máy chủ web bị nhầm lẫn quá nhiều (với khả năng bị mất thông tin hoặc người dùng không thể đăng nhập). Đề nghị của tôi sẽ thất bại hoặc ít nhất là đăng nhập lỗi. –

+2

Hầu như luôn luôn, bạn không muốn 'try/except:' mà không có loại ngoại lệ trong CPython 2.x, bởi vì nó cũng sẽ bắt SystemExit, KeyboardInterrupt và GeneratorExit - đây là tất cả các loại lỗi bạn tốt hơn để lại một mình hoặc, trong trường hợp hiếm hoi, bắt chúng một cách riêng biệt. Đặc biệt trong trường hợp này, ta nên bắt KeyError. Nhưng sau đó bạn có thể tiếp tục làm cho tất cả mã này trở nên đơn giản hơn: 'request.META.setdefault ('REMOTE_ADDR', request.META.get ('HTTP_X_REAL_IP', '1.1.1.1'))' – temoto

+0

Giải pháp hay nhưng hãy nhớ has_key() đã được gỡ bỏ bằng Python 3.x. Sử dụng: nếu không yêu cầu.META.get ('REMOTE_ADDR', Không có): – Robert

5

Thêm "fastcgi_param REMOTE_ADDR $ remote_addr;" đến tập tin nginx.conf:

location/{ 
    # host and port to fastcgi server 
    fastcgi_pass 127.0.0.1:8801; 
    fastcgi_param PATH_INFO $fastcgi_script_name; 
    fastcgi_param REQUEST_METHOD $request_method; 
    fastcgi_param QUERY_STRING $query_string; 
    fastcgi_param CONTENT_TYPE $content_type; 
    fastcgi_param CONTENT_LENGTH $content_length; 
    fastcgi_pass_header Authorization; 
    fastcgi_intercept_errors off; 
    ... 
    # Add this line! 
    fastcgi_param REMOTE_ADDR $remote_addr; 
    ... 
} 

Nguồn: how to nginx virtual servers + fcgi for django?

+0

Điều này hoạt động tốt cho 'fastcgi_pass' (cảm ơn!), Nhưng nó sẽ không hoạt động đối với' proxy_pass', đó là thiết lập của OP (xem @windyjonas 'câu trả lời). –

+1

Làm thế nào về - 'fastcgi_param REMOTE_ADDR $ http_x_real_ip;'? Nếu X-Real-IP có sẵn cho nginx, nó có thể được sử dụng để truyền vào như fastcgi_param. Điều đó sẽ loại bỏ cần phải thực hiện thay đổi trong mã nguồn ứng dụng. – rahul286

2

Đối với tôi, bằng cách sử dụng hoạt động sau đây:

server { 
    listen 80; 
    server_name foo.bar.com; 
    location/{ 
     proxy_pass http://127.0.0.1:8000; 
     proxy_set_header X-Forwarded-For $remote_addr; 
    } 
} 

này làm việc với django 1,4 (đặc biệt là localshop).

Các vấn đề liên quan