Rails에서 request.remote_ip와 request.ip의 차이점은 무엇입니까?
제목이 진행됨에 따라 두 가지 방법으로 클라이언트의 IP를 얻을 수 있습니다. 차이점이 있는지 궁금합니다. 감사합니다.
소스 코드에는
"/usr/local/rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action _dispatch / http / request.rb"257L, 8741C
def ip
@ip ||= super
end
# Originating IP address, usually set by the RemoteIp middleware.
def remote_ip
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
end
그러나 나는 정말로 의미를 모릅니다.
출처 :
module ActionDispatch
class Request < Rack::Request
# ...
def ip
@ip ||= super
end
def remote_ip
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
end
# ...
end
end
Rack :: Request는 다음과 같습니다.
module Rack
class Request
def ip
remote_addrs = split_ip_addresses(@env['REMOTE_ADDR'])
remote_addrs = reject_trusted_ip_addresses(remote_addrs)
return remote_addrs.first if remote_addrs.any?
forwarded_ips = split_ip_addresses(@env['HTTP_X_FORWARDED_FOR'])
if client_ip = @env['HTTP_CLIENT_IP']
# If forwarded_ips doesn't include the client_ip, it might be an
# ip spoofing attempt, so we ignore HTTP_CLIENT_IP
return client_ip if forwarded_ips.include?(client_ip)
end
return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"]
end
end
end
그래서 remote_ip
에 우선 순위를 제공합니다 action_dispatch.remote_ip
. 그것은 ActionDispatch::RemoteIp
미들웨어에 의해 설정되고 있습니다. 해당 미들웨어의 소스에서 호출 될 때 스푸핑 공격을 확인하고 있음을 알 수 있습니다 GetIp.new
. 해당 환경 변수를 설정하기 위해 호출 하기 때문 입니다. remote_ip
Clowerweb이 설명했듯이 로컬 프록시를 통해서도 IP 주소를 읽기 때문에 필요 합니다.
request.ip
returns the client ip
even if that client is a proxy.
request.remote_ip
is smarter and gets the actual client ip
. This can only be done if the all the proxies along the way set the X-Forwarded-For header.
request.ip
request.ip
is the basic ip detection provided by Rack::Request
out of the box. Its current definition can be found at https://github.com/rack/rack/blob/master/lib/rack/request.rb.
The algorithm it follows is to first check the REMOTE_ADDR
header for any untrusted IP addresses, and if it finds any, it chooses the first one listed. "Trusted" IP addresses in this case are IP addresses from the reserved private subnet ranges, but note that it matches by regex which is probably not the best way to do it. If there is no untrusted REMOTE_ADDR
then it looks at the HTTP_X_FORWARDED_FOR
header, and picks the last untrusted one listed. If neither of those reveals anyone it falls back to the raw REMOTE_ADDR
which is probably 127.0.0.1.
request.remote_ip
request.remote_ip
is enhanced IP detection provided by ActionDispatch::Request
(which inherits from Rack::Request
). This is the code shown in the question. As you can see, it falls back to request.ip
unless action_dispatch.remote_ip
is set on the @env
. That is done by the RemoteIp
middleware, which is included in the default Rails stack. You can see its source at https://github.com/rails/rails/blob/4-2-stable/actionpack/lib/action_dispatch/middleware/remote_ip.rb.
The RemoteIp
middleware if enabled provides these additional features:
- Provides optional but default IP spoofing detection.
- Allows configuration proxy addresses to be filtered instead of relying only on defaults.
- Uses the
IPAddr
class to actually test IP ranges properly instead of relying on a brittle regex. - Uses
HTTP_CLIENT_IP
as a source of potential IPs.
The algorithm is similar to request.ip
but slightly different. It uses HTTP_X_FORWARDED_FOR
from last to first, then HTTP_CLIENT_IP
from last to first, then finally the last entry of REMOTE_ADDR
. It puts those all in a list and filters proxies, picking the first remaining one.
IP Spoofing Detection
The IP spoofing detection provided by RemoteIp
is not particularly powerful, all it does is raise an exception if the last HTTP_CLIENT_IP
is not in HTTP_X_FORWARDED_FOR
. This isn't necessarily a symptom of an attack, but it is probably a symptom of a misconfiguration or a mix of proxies using different conventions which are not producing a coherent result.
Which to Use
In a simple setup where your proxies are all local or on private subnets, you can probably get away with request.ip
, but request.remote_ip
should be considered the superior choice in general. If you are using proxies with public internet routing (such as many CDNs) then RemoteIp
can be configured to give you correct client IPs out of the box, whereas request.ip
will only be correct if you can get your upstream proxy to set REMOTE_ADDR
correctly.
Secure Configuration
Now to address Tim Coulter's comment about spoofing. He's definitely right you should be concerned, but he's wrong that you can be spoofed if you're behind nginx or haproxy by default. RemoteIp
is designed to prevent spoofing by choosing the last IP in the chain. The X-Forwarded-For spec specifies that each proxy append the requester's IP to the end of the chain. By filtering out whitelisted proxies, the last entry is guaranteed to be the client IP written by your first whitelisted proxy. There is one caveat of course, which is that you must actually be running a proxy that always sets/appends X-Forwarded-For
, so Tim's advice should actually be opposite: only use request.remote_ip
when you are running a proxy.
How To Configure for Public IP Proxies
That's all fine and good, but ActionDispatch::RemoteIp
is already in the default middleware stack. How do reconfigure it to add my proxy CIDRs?!
Add this to your application.rb
:
check_spoofing = true
proxies = ["23.235.32.0/20", "203.57.145.0/24"]
proxies += ActionDispatch::RemoteIp::TRUSTED_PROXIES
config.middleware.swap ActionDispatch::RemoteIp,
ActionDispatch::RemoteIp,
true,
proxies
'Programing' 카테고리의 다른 글
문자열 수식을 "실제"수식으로 바꾸는 방법 (0) | 2020.11.18 |
---|---|
이미지와 텍스트 모두 가능한 UIButton? (0) | 2020.11.17 |
git이 "~"로 끝나는 모든 파일을 추적하지 못하도록하는 방법은 무엇입니까? (0) | 2020.11.17 |
특정 클래스가있는 요소를 어떻게 선택합니까? (0) | 2020.11.17 |
Python 로그 형식 문자열에 사용자 정의 필드를 어떻게 추가합니까? (0) | 2020.11.17 |