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.