[AWS] Lambda: 고정 IP 프록시 만들기

내 서버 환경의 경우에는 Fargate 스택들을 써서 서버 IP가 계속 바뀌었다.

근데 서드파티 API를 제공할 때는, IP를 고정하고 그 IP에서만 API를 사용할 수 있게끔 보안적인 제약을 가하는 경우가 종종 있다.

EC2나 EKS 스택을 사용한다면 이걸 어느 정도 대응할 수 있지만, Fargate 기반의 스택에서는 이게 좀 어렵다.

서버를 전부 private 서브넷에 두고 NAT Gateway를 통해서 나가게 하면 NAT의 IP를 고정 IP로 쓸 수 있지만, NAT 통신비용이 좀 비싸다는게 비용적 문제가 될 수도 있다.
내 경우에는 서버에서 발생하는 트래픽 양이 월에 NN 테라급이었고, 이걸 전부 NAT으로 타게만 하면 비용적 비효율이 발생했다.

그래서 고정 IP가 필요한 API 작업만 고정 IP 프록시를 타도록 구성할 필요가 있었는데, EC2는 확장이 어렵고 변칙적인 사용 패턴에 있어서는 효율적이지 않아서 Lambda를 선택했다.

Lambda를 private 서브넷에 두고 NAT Gateway를 통하게만 유도하면 그 자체로 고정 IP 프록시로 쓸 수 있는 것이다.
게다가 관리도 별로 필요없다.

우선은 당연히 NAT 구성이 되어있어야 한다.


Lambda를 VPC 구성으로 만들고, Function URL을 땄다.


vpc 설정에서 private 서브넷만 물도록 설정한다.


import axios from 'axios';

export const handler = async (event) => {
  // console.log(event);

  try {
    const url = event.requestContext?.http?.path; 
    const method = event.requestContext?.http?.method;
    const query = event.rawQueryString;
    const body = event.body; 
    const headers = event.headers;

    if(headers?.host) {
      delete headers?.host;
    }

    if(headers?.['x-forwarded-for']) {
      delete headers['x-forwarded-for'];
    }

    let routed_url = '';
    if(url.startsWith('/proxy_test')) {
      routed_url = url.replace('/proxy_test', 'https://....');
    } else if (url.startsWith('/naver')) {
      routed_url = url.replace('/naver', 'https://naver.com');
    } else {
      return {
        statusCode: 403,
        body: {
          response: {
            body: 'NOT ALLOWED',
            statusCode: 403, 
          },
        },
      };
    }

    console.log('routed_url', routed_url);

    if(query != '') {
      routed_url + '?' + query;
    }

    const response = await axios({
      method: method,
      url: routed_url,
      headers: headers,
      body,
      validateStatus: function (status) {
        return status < 500; // 오직 5xx 상태 코드만 실패 처리
      }
    });

    let statusCode = 200;
    if(response) {
      statusCode = response?.status;
    }

    return {
      statusCode,
      headers: headers,
      body: response.data,
    };
  } catch(error) {
    return {
      statusCode: 200,
      body: String(error),
    };
  }
};

그리고 대충 이런 식으로 프록시 코드를 작성했다.
그냥 헤더랑 값들 그대로 포워딩하도록 했다.

/proxy_test 경로에서 라우팅한 API는 요청자의 IP를 echo해주는 간단한 API다.

그리고 실행해보면

몇번을 실행하더라도 같은 IP임을 확인해줄 것이다.

이제 저 고정 IP를 허용목록에 넣어두고, 이 프록시를 통해 호출하도록 하면 된다.



참조
https://repost.aws/knowledge-center/lambda-static-ip