iptables를 사용하여 외부 요청을 localhost로 리디렉션

iptables를 사용하여 외부 요청을 localhost로 리디렉션

일부 X 포트의 "localhost" 주소에서 실행되는 서비스가 있습니다. 아쉽게도 주소를 "0.0.0.0"으로 변경하여 서비스를 노출할 수는 없습니다.

iptables를 사용하여 외부 요청을 루프백/localhost 인터페이스로 내부적으로 리디렉션할 수 있나요? 리디렉션은 0.0.0.0:X -> localhost:X입니다.

감사해요

답변1

OP에서는 방화벽의 존재에 대해 언급하지 않았으므로 단순화를 위해 사전에 방화벽이 없다고 가정하겠습니다.iptables설정이 존재합니다: 모든 트래픽을 허용합니다.

DNAT다음과 같이 사용할 수 있습니다.nat/프리라우트다음과 같이 대상 IP를 127.0.0.1로 변경합니다(UDP 포트 5555를 리디렉션하는 예).

# iptables -t nat -A PREROUTING -p udp --dport 5555 -j DNAT --to-destination 127.0.0.1

하지만이는 127.0.0.0/8 범위 외부의 시스템에 있는 모든 로컬 IP 주소에 대한 모든 DNAT 대상에 충분합니다. 대상을 127.0.0.0/8 내의 IP 주소로 변경하는 특정 경우에는 이것만으로는 충분하지 않습니다.

이것이 제대로 작동하려면 전환해야 하는 특별한 설정이 있습니다. 시스템의 네트워크 인터페이스가 다음과 같이 호출된다고 가정합니다.이더넷 0이 명령은 다음을 수행합니다.

# sysctl -w net.ipv4.conf.eth0.route_localnet=1

아래의 자세한 설명을 참조하세요.

(선택 사항) 특히 127.0.0.1에서 수신 대기하는 애플리케이션에 127.0.0.0/8 이외의 소스 IP가 필요하지 않은 경우 변경할 수도 있습니다.자연/입력사슬로 묶다네트워크 주소 변환. 대상과 소스를 NAT하면 동시 연결 수가 심각하게 제한되므로 필요할 때만 수행해야 하며 더 이상 로그에서 실제 소스를 얻을 수 없습니다.

# iptables -t nat -A INPUT -d 127.0.0.1 -m state --ctstate DNAT -j SNAT --to-source 127.0.0.1

사용법에 대한 자세한 설명route_localnet=1

아래에서 문제를 더 자세히 설명하기 위해 다음과 같이 가정하겠습니다. 호스트의 네트워크 인터페이스는 다음과 같습니다.이더넷 0, 이 인터페이스에 설정된 IP 주소는 192.0.2.100/24이며 클라이언트 192.0.2.200에서 트래픽을 수신하지만 route_localnet아직 활성화되지 않았습니다.

볼 수 있어야합니다일반 네트워크의 Netfilter 및 패킷 흐름(전체 크기를 보려면 클릭하세요):

일반 네트워크의 Netfilter 및 패킷 흐름

일이 발생한 순서를 확인하세요.

  • 클라이언트는 192.0.2.200에서 192.0.2.100(UDP 대상 포트 5555)으로 패킷을 보냅니다.

  • nat/프리라우트발생하다

    대상은 127.0.0.1로 변경됩니다(해당 conntrack 항목은 이 변경 사항을 되돌리는 데 사용됩니다).

  • 라우팅 스택은 도착하는 패킷을 처리합니다.이더넷 0소스 주소는 192.0.2.200이고 대상 주소는 127.0.0.1입니다.

  • lo127.0.0.1은 루프백 인터페이스 외부에 나타나지 않기 때문에 라우팅 스택은 이 패킷을 유효하지 않은 것으로 간주합니다 . 패킷이 삭제됩니다.

    이는 다음을 통해 확인할 수 있습니다 ip route get.

    # ip route get 127.0.0.1 from 192.0.2.200 iif eth0
    RTNETLINK answers: Invalid argument
    

    게다가 커널을 활성화하고 싶다면화성 기록( sysctl -w net.ipv4.conf.eth0.log_martians=1), 이 정보는 DNAT 동안 수신된 각 패킷에 대해 기록됩니다.iptables위의 규칙이 작동합니다.

    [728538.240893] IPv4: martian destination 127.0.0.1 from 192.0.2.200, dev eth0
    

이것이 필요한 드문 경우에 커널에는 이 동작을 완화하기 위한 특정 스위치가 있으며, 이 특정 경우와 마찬가지로 패킷에 127.0.0.1이 나타나는 이유는 DNAT 규칙 때문이라는 것을 알고 있습니다.route_localnet:

route_localnet - BOOLEAN
  Do not consider loopback addresses as martian source or destination
  while routing. This enables the use of 127/8 for local routing purposes.
  default FALSE

존재하다이더넷 0:

# sysctl -w net.ipv4.conf.eth0.route_localnet=1

이제 이전 ip route get명령은 다음을 제공합니다.

# ip route get 127.0.0.1 from 192.0.2.200 iif eth0
local 127.0.0.1 from 192.0.2.200 dev lo 
    cache <local> iif eth0 

더 이상 방울이 없습니다.

이는 또한 반대 방식으로 동일한 제한을 완화합니다. 첫 번째 단계로 응답 패킷은 라우팅 결정을 통과합니다.앞으로DNAT는 netfilter에 의해 취소되므로 역시 삭제됩니다. 이전 및 이후 경로는 route_localnet1로 설정됩니다.

앞으로:

# ip route get 192.0.2.200 from 127.0.0.1
RTNETLINK answers: Invalid argument

뒤쪽에:

# ip route get 192.0.2.200 from 127.0.0.1
192.0.2.200 from 127.0.0.1 dev eth0 uid 0 
    cache 

답변2

예, 가능합니다.

다음 명령 시퀀스가 ​​트릭을 수행해야 합니다.

INTERFACE_IP="192.168.0.1"  # IP address of the external interface (e.g. eth0)
INTERFACE_PORT="80"         # external port to forward
LOCAL_IP="127.0.0.1"        # internal ip address to forward to
LOCAL_PORT="8080"           # internal port to forward to
/usr/sbin/iptables -t nat -A PREROUTING -d $INTERFACE_IP --dport $INTERFACE_PORT -j DNAT --to-destination $LOCAL_IP:$LOCAL_PORT

또는 약간 덜 역동적입니다.

/usr/sbin/iptables -t nat -A PREROUTING -d 192.168.0.1 --dport 80 -j DNAT --to-destination 127.0.0.1:8080

대상 포트(:8080)가 수신 포트와 동일한 경우 생략 가능합니다.

iptables의 다른 규칙으로 인해 이 규칙에 문제가 발생할 수 있다는 점에 유의하세요!

관련 정보