Express.js req.ip가 :: ffff : 127.0.0.1을 반환합니다.


99

현재 요청한 사용자의 IP를 얻으려고합니다. 문제는 IP가 ::ffff:127.0.0.1대신 반환된다는 것입니다 127.0.0.1. 나는 trusted proxy옵션을 사용하려고 시도했지만 (프록시를 사용하지 않지만) req.ips비어 있습니다. 4.x Express.js 사용.

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});

그래서 무엇을 사용 req.ip하고 req.ips있습니까?
Aleksandr M

req.ip, 방금 req.ips테스트로 시도 했습니다. 접두사의 원인이 무엇인지 잘 모르겠습니다 ::ffff:.
rockerBOO 2015


네, 그랬습니다. Windows 7에는 IPv4 요청을위한 전환 계층이 있으며이 접두사를 IP에 추가합니다.
rockerBOO 2015

답변:


157

::ffff:IPv6 (128 비트) 공간 내에 배치되는 IPv4 (32 비트) 주소의 서브넷 접두사입니다. IPv6는 서브넷 접두사와 인터페이스 접미사의 두 부분으로 나뉩니다. 각각의 길이는 64 비트 또는 4 개의 16 진수 문자로 구성된 4 개의 그룹입니다.

IPv6를, 당신은 의미가 연속 0을 앞에 0을 제거하고 제거 할 수 있습니다 ::ffff:사실로 변환 0000:0000:ffff:0000어떤 IPv6의 프로세서는 IPv4 주소와 함께 일하고 이해하고 처리 할 수 있도록이 주소는 IPv6를 서브넷 접두사는 IPv4로 지정되어 있습니다, 따라서.

가까운 장래에 IP 주소는 모두 IPv6이 될 것입니다. 이는 IPv4 주소 공간에서 거의 숫자가 부족하기 때문입니다 (42 억, 기타 목적을위한 공간 제외).

IPv6는 훨씬 더 큰 공간을 허용합니다. "누구에게나 340 억 달러면 충분해야합니다"-Bill Gates가 IPv6에 대해 이야기합니다.

IPv6 네임 스페이스를 사용하여 IP 주소 주소 지정을 시작하는 것이 중요하므로 ::ffff:나중에 해당 콜론 사이에 실제 16 진수 데이터가있을 것이므로 코드에를 포함 해야합니다. 미적 이유로 제거하면 IPv6 네트워크로 전환하거나 IPv6 주소와 마주 칠 때 코드가 손상됩니다.

일부 네트워크는 현재 IPv6를 실행하고 있으며 곧 IPv6 IP 주소에 직면하게 될 것입니다. 지금 도약하지 않으면 나중에 코드가 깨질 위험이 있습니다.

문제의 TL; DR (짧은) 버전은 다음과 같습니다. 모든 것이 잘 작동합니다. 변경하지 마십시오. IPv4 주소의 IPv6 버전입니다.

IPv4 IPv6

코드가 IPv6과 호환되도록하려면 ::ffff:접두사를 확인하기 만하면됩니다 ... 존재하는 경우 제거하고 나머지를 IPv4로 처리합니다 ... ::ffff:존재하지 않는 경우 IPv6 주소이고 처리해야합니다. 문자열에 마침표가 있는지 확인하여 다시 확인할 수 있습니다. 그렇다면 IPv4입니다.

IP 주소에 대한 조정을 제외하고 모든 것을 염두에 두십시오. IP를 기록하는 것입니다. 이는 파서 및 로그 집계에 중요 할 ::ffff:127.0.0.1것입니다. IP를 변경할 필요가 없다면받은 그대로 두십시오.


하지만 접두사확인하는 것은::ffff: 상당히 위험 해 보입니다. 알다시피 IPv6에는 많은 표기법이 있습니다.
Константин Ван

1
아니오 그것은 안전합니다 :) 제안이 있고 구현이 있습니다. en.wikipedia.org/wiki/… IETF는 라우터가 IP 주소를 찾는 많은주기를 태울 수 없다는 것을 인식하고 있으며, 또한 공간 낭비이기 때문에 아무도 0을 유지하지 않습니다. 0을 허용한다는 아이디어는 단지 아이디어였습니다. 2019 년에 네트워크 패킷에서 :: ffff :를 0000 : 0000 : ffff : 0000으로 보낸 경우, 원래 제안에는 기술적으로 유효하지만 현재 IETF 권장 사항에는 유효하지 않으며 대부분의 IPv6 호환 라우터에서 볼 수 없습니다.
Nick Steele

1
그래서 나는 그것들이 항상 표준 형식 에 있다는 것을 확신 할 수 있습니다 . 야생에서 어떻게 돌아가는지 몰랐습니다. 감사.
Константин Ван

불행히도 이것은 일반적입니다. 인간은 필요할 때만주의를 기울입니다. 누군가가 무언가를 초안하고 원래 디자인이 많은 기능을 지원하고 RFC를 만들고 아무도 디자인의 많은 부분에 실제로 관심을 기울이지 않고 표준이 된 다음 구현 된 사람들이 큰 변화가 필요하다는 것을 알았습니다. :) IPv6은 약간 이상합니다. "cannonical"이라고 부르는 게 좀 이상 하거든요 사람들이 무슨 일이 일어나고 있는지 빨리 이해할 수 있도록 "1.1"이라고 부르는 것이 좋겠지 만, 원래 초안의 선택적 0으로 인해 라우터에서 10 배 더 많은 컴퓨팅을 사용할 수 있으므로 무시되었습니다.
Nick Steele

29

이것은 ipv6의 특징 인 것 같습니다. ipv4 주소의 경우 ipv6은 ipv6 표기법과 ipv4 표기법을 혼합 한 것 같습니다.

단순하고 혼합되지 않은 표기법으로 ipv4 및 ipv6 주소를 모두 얻으려면 다음을 사용합니다.

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
if (ip.substr(0, 7) == "::ffff:") {
  ip = ip.substr(7)
}


10

Windows 7에는 기본적으로 IPv6이 활성화되어 있습니다. 내 서버가 IPv4에서만 수신하지만 Windows 7은 ::ffff:IPv6 로의 전환의 일부로 접두사를 IPv4로 보냅니다.

::ffff:0:0:0/96 — SIIT (Stateless IP / ICMP Translation) 프로토콜에서 사용하는 IPv4 변환 주소에 사용되는 접두사입니다.

IPv4에서 전환


8

ipv4 매핑 된 주소를 비교하는 데 문제가 있었고 ipaddr.js 라이브러리가 도움이되는 것을 발견했습니다. :-)

예 :

_.isEqual(ipaddr.process('::ffff:127.0.0.1'), ipaddr.process('127.0.0.1')) === true

3

서브넷을 제거하여 정확한 IP 주소를 얻으려면 이것을 시도하십시오.

    let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    ip = ip.toString().replace('::ffff:', '');

-2

소켓을 사용하여 Ip 주소를 단독으로 또는 지정된 제품군으로 가져올 수 있습니다.

     var app = require('express')();

 app.get("/ip", (req, res) => {
        console.log(req.ip) 
       let ip = req.ip.split(':');
        let ip_details = req.socket.address();
          console.log(ip_details);                     
   // { address: '::ffff:127.0.0.1', family: 'IPv6', port: 3001 

           console.log(ip[3]);//127.0.0.1
                            res.json(ip[3]);  
      }

-2
var ip = req.ip.split(':').pop();

다른 답변에서 설명 하듯이 이것은 IPv6 주소입니다. 위의 @Nick Steele의 답변을 참조하십시오. 당신은 정말로 이것을하고 싶지 않습니다.
Misha Nasledov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.