Raw소켓에 대해서...
뻘짓

Raw소켓에 대해서...

wireshark를 이용해 볼 수 있는 트래픽들

 소켓 프로그래밍을 배우다보면 로우소켓이라는 신비한 존재를 접하게 된다. 처음 이 로우소켓을 보고나면 재밌는것들이 꽤 많이 떠오른다 TCP - SYN Flood 공격, 공격이 아닌 SYN 스캔, TCP의 다양한 플래그를 건드려 보내보는것, IP위조 등등... 네트워크 이론을 공부하며 봐왔던 프로토콜 헤더를 입맛대로 수정해서 전송할 수 있다니 !! (물론 이런걸 타인의 시스템에 쏘면 위법이다...)

 나도 윈도우에서 개발한지가 10년이 되었고 이제 막 리눅스에서 코드를 짜기 시작했는데, 아직도 MS에게 맞은 뒤통수가 얼얼하다. 본론으로 들어가기에 앞서, 나의 뒤통수 일대기를 들려주고자 한다...

 내가 고3때, 소스 IP주소를 위조 해서 여러가지 테스트를 해보고 싶었다. 로우소켓의 존재를 알았고, 그 점을 적극 활용하여 네트워크를 들쑤셔볼 수 있는 위조패킷 전송툴을 만들고자 했다. 그런데 세상에... 마이크로소프트는 개인 사용자의 PC를 감염시켜 동작하는 악성 소프트웨어로부터 기인된 네트워크 공격을 원천차단하기 위해 이 로우소켓의 기능을 대폭 제한해버린것이다.

 윈도우즈 환경에서는 TCP에 대한 로우소켓이 생성되지 않는다. WSAGetLastError 함수로 확인해보면 허용되지 않는 접근이라는 다소 황당한 에러가 반환될 뿐이다. (관리자 권한임에도 불구하고) 그래서 로우소켓으로는 꼴랑 UDP 같은 프로토콜 스택으로만 생성 할 수 있었다.

 그러나 마이크로소프트는 거기서 그치지 않았다. IP 헤더에 대해서도 제한을 먹여놨는데, 바로 소스 IP 주소가 자기 자신의 주소가 아니면 송신이 되지 않는다는 빅 엿을 먹여버린것이다. IP 위조가 원천적으로 불가능한 환경이라는 이야기다. 전문가들이 윈도우 환경에서 작업 하지 않는 이유가 벌써부터 보인다... 심지어 2계층으로 내려가, 이더넷이나 802.11을 조작하는것은 소켓이라는 인터페이스로는 그 태생부터 접근이 불가능하다.

 그럼에도 불구하고 나는 이 제한을 우회하기 위해 드라이버 레벨로 내려가면 되지 않을까 하는 막연한 희망이 있었고 그로부터 7년이 지난 지금 또 통수를 맞았다.

 이전에도 포스팅했던 NDIS 드라이버를 이용한 WIFI 전파 도청이 그것인데, 랜카드가 모니터 모드로 동작중인경우 데이터를 송신하는것이 불가능하다고 공식 MSDN에 명시 되어있었다. 뭔놈의 운영체제가 되는게 없냐 진짜...

 물론 최하단에서 동작하는 WLAN 디폴트 드라이버에 직접 물려서 강제적으로 송신할 수는 있지만, 그거 하나 하겠다고 이렇게까지 깊이 들어가야 하는 것 자체가 이 윈도우가 얼마나 폐쇄적인지 느끼게 해준다. 여러분도 말로만 "윈도우가 폐쇄적이고 오픈소스가 아니여서 뭐가 힘드네 마네" 이런 소리 듣기만 했지, 실제로 어떤 제한이 있고 어떤 어려움이 있는지 몰랐을것이다.

아무튼 돌고돌아 여기까지 왔는데, 결론은 오늘은 리눅스에서 프로그래밍 하는 이야기이다. 

 

 리눅스에서 로우소켓의 사용은 상당히 자유로웠다. TCP를 조작하던 IP를 조작하던, 심지어 이더넷프레임까지 맘대로 조작할수도 있었고 ARP, ICMP같은 프로토콜도 자유롭게 조작해 사용할 수 있었다.

이 리눅스도 로우소켓에 약간의 제약은 있다. 하지만 구조적인 이유의 제약만 있을뿐이다. 

 대표적인 리눅스 로우소켓의 제약은 L3 계층의 로우소켓은 수신이 불가능하다는것이다. 여기서 L3 계층의 로우소켓이란, 다음과 같은 함수콜로 생성된 소켓을 말한다.

 AF_INET 으로 L3계층 상단부터 데이터를 핸들링하도록 하고 SOCK_RAW 를 줌으로써, 이 계층의 데이터는 응용프로그램이 직접 다룬다고 선언한다. 그리고 IPPROTO_RAW를 줌으로써 어떤 특정한 프로토콜에 국한된것이 아닌, 전부를 아우르는 데이터를 다룰것이라고 일러둔다. 이런 조건으로 생성된 소켓은 "송신만 된다". 즉 14번라인의 L3MonitorSock 은 의미가 없다. 수신이 안되는데 뭘 모니터링하겠는가.

 수신할때는 L3소켓이 아닌 L2 소켓으로 받거나, 아니면 IPPROTO_RAW가 아닌 IPPROTO_TCP같은 특정 프로토콜 데이터만 다루겠다고 선언된 소켓만 가능하다.

나는 좀더 로우레벨을 선호하는 편이어서 2계층 소켓으로 핸들링했다.

 AF_PACKET 을 줌으로써 L2계층부터 핸들링 할것을 알리고 SOCK_RAW를 줌으로써 이 계층의 데이터부터 응용프로그램이 직접 다룬다고 선언한다. ETH_P_ALL 을 줌으로써 이더넷 데이터를 전반적으로 아우를것이라고 일러둔다. 주의해야 할 점이라면 맨 마지막 인자는 네트워크 바이트오더로 줘야 한다는것이다. htons로 감싸주자.

 ETH_P_ALL 말고도 특정 종류의 프레임을 다루고 싶다면 이런 상수들을 사용 할 수 있다. if_ether.h 헤더파일에 정의 되어있으므로 인클루드 해서 사용 하도록 하자. 화면은 왠지 비주얼 스튜디오지만 리눅스용 코드 맞다. 비주얼스튜디오를 리눅스에 원격으로 붙여서 사용하는 방법은 아래 글을 참조 해보자.

https://nitwit.tistory.com/32?category=543911 

 

Visual Studio 리눅스 원격 디버깅

 리눅스의 자유로운 개발 환경은 정말 매력적이다. 특히 서버의 경우엔, 별도의 라이센스 없이도 무료로 사용 할 수 있는 프리웨어이기 때문에 기업의 경우 라이센스 유지 비용에 대해서 완전

nitwit.tistory.com

 

요약 하자면 다음과 같다.

1. 윈도우에서 로우소켓은 UDP 로우소켓만 생성이 가능하다. TCP는 안된다.

2. 윈도우에서 로우소켓은 IP헤더까지 다룰수 있도록 옵션을 주더라도 소스 IP는 변조가 불가하다.

3. 윈도우에서 소켓 인터페이스로는 이더넷, 802.11과 같은 MAC 계층 프레임엔 접근조차 불가하다.

4. 리눅스 로우소켓은 자유롭다.

5. 리눅스 로우소켓은 IPPROTO_RAW 옵션으로 생성된 소켓으로는 송신만 가능하고 수신은 불가능하다.