
빠른 브라우저 기반 네트워크 검색 모듈
빠른 브라우저 기반 네트워크 검색 모듈
이 프로젝트는 더 이상 유지 관리되지 않습니다.
netmap.js는 브라우저 기반 호스트 검색 및 포트 스캔 기능을 제공하여 웹사이트 방문자의 네트워크를 매핑할 수 있게 해줍니다.
매우 빠르며, es6-promise-pool을 활용하여 브라우저가 허용하는 최대 동시 연결 수를 효율적으로 실행합니다.
작업 중인 아이디어를 위해 브라우저 기반 포트 스캐너가 필요했습니다. 기존 모듈을 가져오거나 BeEF 같은 다른 프로젝트에서 코드를 복사-붙여넣기 하면 간단할 줄 알았습니다.
하지만 사용하기 좋은 기성 npm 모듈이 없었고, BeEF의 port_scanner 모듈은 (글을 쓰는 시점에서) 부정확하고 느리며 Chromium에서 작동하지 않았습니다.
따라서 netmap.js는 모든 최신 브라우저에서 작동하는, 어느 정도 최적화된 "핑" 스위퍼 및 TCP 스캐너입니다.
npm install --save netmap.js
홈 환경에서 가능성이 높은 후보 목록을 시작으로 웹사이트 방문자의 게이트웨이 IP 주소를 알아내 봅시다:
import NetMap from 'netmap.js'
const netmap = new NetMap()
const hosts = ['192.168.0.1', '192.168.0.254', '192.168.1.1', '192.168.1.254']
netmap.pingSweep(hosts).then(results => {
console.log(results)
})
{
"hosts": [
{ "host": "192.168.0.1", "delta": 1003, "live": false },
{ "host": "192.168.0.254", "delta": 1001, "live": false },
{ "host": "192.168.1.1", "delta": 18, "live": true },
{ "host": "192.168.1.254", "delta": 1002, "live": false }
],
"meta": {}
}
호스트 192.168.1.1이 활성 상태인 것으로 보입니다.
몇몇 호스트에서 열려 있는 TCP 포트를 찾아봅시다:
import NetMap from 'netmap.js'
const netmap = new NetMap()
const hosts = ['192.168.1.1', '192.168.99.100', 'google.co.uk']
const ports = [80, 443, 8000, 8080, 27017]
netmap.tcpScan(hosts, ports).then(results => {
console.log(results)
})
{
"hosts": [
{
"host": "192.168.1.1",
"control": "22",
"ports": [
{ "port": 443, "delta": 15, "open": false },
{ "port": 8000, "delta": 19, "open": false },
{ "port": 8080, "delta": 21, "open": false },
{ "port": 27017, "delta": 26, "open": false },
{ "port": 80, "delta": 95, "open": true }
]
},
{
"host": "192.168.99.100",
"control": "1001",
"ports": [
{ "port": 8080, "delta": 40, "open": true },
{ "port": 80, "delta": 1001, "open": false },
{ "port": 443, "delta": 1000, "open": false },
{ "port": 8000, "delta": 1004, "open": false },
{ "port": 27017, "delta": 1000, "open": false }
]
},
{
"host": "google.co.uk",
"control": "1001",
"ports": [
{ "port": 443, "delta": 67, "open": true },
{ "port": 80, "delta": 159, "open": true },
{ "port": 8000, "delta": 1001, "open": false },
{ "port": 8080, "delta": 1002, "open": false },
{ "port": 27017, "delta": 1000, "open": false }
]
}
],
"meta": {}
}
처음에는 결과가 모순되어 보일 수 있습니다.
192.168.1.1은 로컬 네트워크 세그먼트에 있는 임베디드 Linux 머신(라우터)이며, 열려 있는 유일한 포트는 80입니다. 브라우저가 다른 닫힌 포트에 비해 80에서 오류를 발생시키는 데 약 5배 더 오래 걸린 것을 볼 수 있습니다.
192.168.99.100은 호스트 전용 VM이며 포트 8080이 열려 있고, google.co.uk는 외부 호스트로 443과 80이 모두 열려 있습니다. 이 경우 브라우저는 열린 포트에서 상대적으로 빠르게 오류를 발생시킨 반면, 닫힌 포트는 단순히 타임아웃되었습니다. 아래 이론 섹션에서 이 현상이 언제 발생하는지 설명합니다.
포트를 열림 또는 닫힘으로 태그할지 결정하기 위해, netmap.js는 닫혀 있다고 가정되는 "컨트롤" 포트(기본값 45000)를 스캔합니다. 그런 다음 control 시간을 사용하여 다른 포트의 상태를 결정합니다. delta/control 비율이 설정된 값(기본값 0.8)보다 크면 포트가 닫힌 것으로 간주됩니다(요약: 컨트롤 시간과 20% 이상 차이가 나면 포트가 열린 것을 의미합니다).
브라우저는 연결을 거부하는 포트 블랙리스트를 유지 관리합니다(FTP, SSH, SMTP 등). 기본 프로토콜(http)을 사용하여 netmap.js로 해당 포트를 스캔하려고 하면 매우 짧은 타임아웃이 발생합니다. 짧은 타임아웃은 일반적으로 포트가 닫혔다는 신호이지만, 블랙리스트에 있는 포트의 경우에는 아무 의미가 없습니다.
다음 출처에서 블랙리스트를 확인할 수 있습니다:
Firefox 61 (및 다른 브라우저) 이전에는 http 대신 ftp 프로토콜을 사용하여 연결을 설정함으로써 이 제한을 우회할 수 있었습니다. NetMap을 인스턴스화할 때 옵션 객체에서 protocol을 지정할 수 있습니다. ftp를 사용할 때는 열린 포트가 타임아웃되고 닫힌 포트가 상대적으로 빠르게 오류를 발생시킬 것으로 예상해야 합니다. ftp 스캐닝은 또한 이 문서에서 논의된 TCP RST 패킷 관련 제한 사항의 영향을 받습니다.
ftp와 같은 "레거시" 프로토콜의 하위 리소스 요청은 Chromium에서 한동안 차단되었습니다.
netmap.js에서 제공하는 "핑" 스위프 기능은 로컬 네트워크 세그먼트에서 *nix 기반 호스트(다른 컴퓨터, 전화기, 라우터, 프린터 등)를 빠르게 찾는 데 꽤 효과적입니다.
그러나 구현 방식 때문에 TCP RST 패킷이 반환되지 않으면 작동하지 않습니다. 일반적으로:
그 이유는 아래 이론 섹션에서 설명합니다.
이 제한은 TCP 스캔 기능에는 영향을 미치지 않으며, 위 호스트에서 열린 포트를 찾아 활성 여부를 판단하는 것은 여전히 가능합니다.
전반적으로, 이 모듈은 웹에서 발견한 다른 코드 조각들보다 더 정확하고 빠른 것으로 확인되었습니다. 그렇긴 하지만, 브라우저에서 네트워크를 매핑한다는 개념 자체가 본질적으로 까다롭습니다. 사용 환경에 따라 결과가 다를 수 있습니다.
NetMap 생성자NetMap 생성자는 다음을 구성할 수 있는 옵션 객체를 받습니다:
protocol (기본값 http, 포트 블랙리스트에서 ftp로 설정하려는 이유 참조)timeout (기본값 1000 밀리초)import NetMap from 'netmap.js'
const netmap = new NetMap({
protocol: 'http',
timeout: 3000
})
pingSweep()pingSweep() 메서드는 주어진 호스트 배열이 활성 상태인지 판단합니다. 포트 연결 시간이 초과되면 호스트가 오프라인인 것으로 간주합니다(제한 사항은 "핑" 스위프 참조, 이론은 표준 케이스 참조).
이 메서드는 다음 매개변수를 받습니다:
hosts - 스캔할 호스트 배열 (IP 주소 또는 호스트 이름)options 객체:
maxConnections - 최대 동시 연결 수 (기본값: Chrome에서는 10, 다른 브라우저에서는 17 - 브라우저가 지원하는 최대 동시 연결 수)port (기본값 45000)프라미스를 반환합니다.
netmap.pingSweep(['192.168.1.1'], {
maxConnections: 5,
port: 80
}).then(results => {
console.log(results)
})
tcpScan()tcpScan() 메서드는 여러 대상에 대해 포트 스캔을 수행합니다. 작동 방식은 표준 케이스를 참조하세요.
이 메서드는 다음 매개변수를 받습니다:
hosts - 스캔할 호스트 배열 (IP 주소 또는 호스트 이름)ports - 스캔할 포트 목록 (1-65535 사이의 정수, 블랙리스트에 있는 포트는 피하세요)options 객체:
maxConnections - 최대 동시 연결 수 (기본값 6 - 브라우저가 도메인별로 허용하는 최대 연결 수)portCallback - 개별 host:port 조합 스캔이 완료될 때 실행할 콜백controlPort - 닫힌 포트의 기준 델타를 결정하기 위해 스캔할 포트 (기본값 45000)controlRatio - 포트가 닫힌 것으로 간주되기 위한 컨트롤 델타와의 유사성 비율 (기본값 0.8, 예제 참조)프라미스를 반환합니다.
netmap.tcpScan(['192.168.1.1'], [80, 27017], {
maxConnections: 5,
portCallback: result => {
console.log(result)
},
controlPort: 45000,
controlRatio: 0.8
}).then(results => {
console.log(results)
})
출력을 해석하려면 예제를 확인하세요.
이 섹션에서는 모듈의 검색 기술 뒤에 있는 이론을 간략히 다룹니다.
이 모듈은 Image 객체를 사용하여 교차 출처 리소스(테스트 중인 http://{host}:{port} URL 시리즈)를 요청합니다. 브라우저가 오류를 발생시키는 데 걸리는 시간(delta) 또는 특정 타임아웃 값 이후에도 오류가 발생하지 않는 것은 검사 중인 호스트와 포트의 상태에 대한 정보를 제공합니다.
활성 호스트는 일반적으로 닫힌 포트에 연결을 시도할 때 TCP RST 패킷으로 상대적으로 빠르게 응답합니다.
포트가 열려 있고 HTTP 서버가 실행 중이 아니더라도, 브라우저는 전체 TCP 연결을 설정한 후 제공된 URL에서 이미지를 가져올 수 없음을 인식하는 데 더 많은 오버헤드가 발생하여 오류를 발생시키는 데 시간이 조금 더 걸립니다.
오프라인 호스트는 당연히 RST로 응답하지 않으며 전체 TCP 연결 설정도 허용하지 않습니다. 브라우저는 타임아웃(~90초) 전까지 연결을 시도합니다. netmap.js는 기본적으로 1000밀리초 동안 대기한 후 타임아웃됩니다.
요약:
delta 매우 짧음delta 약간 더 김표준 케이스는 TCP 포트 스캔 예제의 호스트 192.168.1.1에서 확인할 수 있습니다.
RST 없는 케이스일부 호스트(예: google.co.uk 또는 Windows 호스트) 및 일부 네트워크 설정(예: VirtualBox 호스트 전용 네트워크)은 닫힌 포트에 연결할 때 TCP RST 패킷을 반환하지 않습니다.
이러한 경우, 닫힌 포트는 일반적으로 타임아웃되는 반면 열린 포트는 빠르게 오류를 발생시킵니다.
따라서 RST 패킷이 반환되지 않을 때 pingSweep() 메서드의 구현은 신뢰할 수 없습니다.
요약, TCP RST 패킷이 어떤 이유로 반환되지 않는 경우:
delta 짧음pingSweep()은 닫힌 포트의 타임아웃과 "죽은" 호스트의 타임아웃을 구분할 수 없음이 특수 케이스는 TCP 포트 스캔 예제의 호스트 192.168.99.100 및 google.co.uk에서 확인할 수 있습니다.
WebSocket 및 AJAX를 사용하여 네트워크를 매핑할 수도 있다는 것은 잘 알려져 있습니다.
시도해 보았고(또한 BeEF를 조정하여 port_scanner 모듈을 WebSocket 및 AJAX만 사용하도록 시도했습니다); 두 방법 모두 완전히 신뢰할 수 없는 결과를 산출했습니다.
이와 관련하여 제가 놓친 부분이 있다면 알려주시기 바랍니다.