🙈

⃝ 동글동글 ⃝

🪐ᐩ˖ 🍎

AWS

결제 에러 [Blocked a frame with origin "https://test.pay.com" from accessing a cross-origin frame. Protocols, domains, and ports must match.]

JONG_UK 2024. 9. 6. 18:09
728x90
반응형

회사 PG는 iframe과 팝업 형식으로 호출되고, 해당 창에서 결제가 완료됐을 때 PG SDK에서 내가 설정한 returnUrl을 호출하여 결제를 완료하는 과정에서 cross-origin frame 에러가 발생했었다.

 

[Blocked a frame with origin "https://test.pay.com" from accessing a frame with origin "https://www.example.com". Protocols, domains, and ports must match.]

[Blocked a frame with origin "https://test.pay.com" from accessing a cross-origin frame. Protocols, domains, and ports must match.]

 

즉 cross-origin frame 에러 때문에 결제가 제대로 이루어지지 않았던 것이다.

 

cross-origin frame 에러는 

- Protocol: https://

- Host: www.example.com

- Port: 443(hidden)

위 세 가지 중 단 하나라도 다르다면 Cross-origin으로 간주되어 교차 출처 에러를 발생시키는 것이다.

 

 

왜 에러가 발생했을까??

에러가 발생한 원인은 cross-origin frame 에러였지만, 왜 이 현상이 발생하는지 알 수가 없었다. 그렇게 결제 테스트를 진행하던 도중 우연히 회사 서비스 주소가 두 가지 경로로 "https://www.example.com"과 "https://example.com"(예시 URL) 접속할 수 있다는 현상을 발견했다.

 

 

분명히 "https://www.example.com"으로만 접속이 가능한 줄 알았고, 만약 "https://example.com"으로 접속하면 로드밸런서나 서버의 Nginx에서 "www."를 붙여주는 줄 알았다. 근데 아니었다...

 

확인하기 위해 클라우드 DNS 레코드를 살펴보았더니, "www.example.com"과 "example.com" 둘 다 A 레코드로 잡혀있고, 로드밸런서와 연결되어 있었다. 그래서 A레코드에 설정된 로드밸런서에 의해서 인스턴스로 "www.example.com"과 "example.com"으로 접속이 가능해진 것이었다... 이로 인해 결제 창에서 내가 설정한 returnUrl과 사용자가 접속한 도메인이 달라서 오류가 계속 발생했던 것이었다!

 

 

어떻게 해결해야 할까?

두 가지 경로로 접속이 가능한 서비스 URL을 어떻게 관리해야 할지 생각해 보았다. 

 

먼저 일반적으로 "www.example.com"과 "example.com" 둘 다 허용을 해줘야 하지 않을까 라는 생각이 들었다. 다만 이렇게 진행하면 cross-origin frame 에러를 피할 수 없었다. 만약 둘 다 허용을 해준다면, 프론트에서 returnURL을 동적으로 location을 잡아 설정해 줘야 했으므로, 해당 방식은 완전한 해결책이 아니라고 생각했다.

 

일단 짧은 나의 생각으로 몇 가지 방안을 좀 고민해 봤다.

 

1. DNS에서 "example.com" A 레코드 삭제

2. 로드밸런서에서 "example.com"으로 들어오는 요청은 "www.example.com"으로 변경해서 인스턴스로 전달하기

3. Ngnix에서 "example.com"으로 들어오는 요청에 대해서 Host를 "www.example.com"로 설정해 애플리케이션 서버로 Reverse Proxy 해주기

 

1. DNS에서 "example.com" A 레코드 삭제

먼저 이 방법은 정말 주먹구구식 방식이라 생각했다. 완전한 해결책이 아닌 그냥 에러를 피하기 위한 해결책이라 생각된다. 팀장님이 일단 이걸로 하라 해서 현재 "http://www.example.com"으로만 접속 가능하게만 해두었다.

 

2. 로드밸런서에서 "example.com"으로 들어오는 요청은 "www.example.com"으로 변경해서 인스턴스로 전달하기

이 방법을 진행해 보려고 로드밸런서에 규칙을 추가해서 해봤는데 실패했다. 실패 원인은 아직 모르겠다..

 

3. Ngnix에서 "example.com"으로 들어오는 요청에 대해서 Host를 "www.example.com"로 변경해 return 해주기

서비스 중단이 불가피하기 때문에 시도하지 않았다...

 

서비스 중단을 피하면서 두 도메인 모두 접속이 가능하도록 어떻게 해야 상용 서비스에 원활하게 적용해야 할지 모르겠어서 그냥 내가 직접 도메인을 구매해서 깔끔한 해결책을 찾을 생각이다.

 

 

내가 직접 해보자

내가 직접 도메인 테스트를 진행해 보려고 일단 가비아에서 도메인을 구매했다.

 

간단하게 가비아에서 구매한 도메인을 AWS Route53 호스팅 영역을 생성해 주고, 미리 만들어둔 EC2의 Public IP를 내가 생성한 A 레코드에 연결해 주었다.

 

 

EC2에는 간단히 Nginx만 설치하고, 서버 접속이 잘 되는지만 확인했다.

 

 

"http://www.juclass.co.kr"과 "http://juclass.co.kr" 두 도메인으로 접속이 잘 되는 것을 확인했다.

 

이제 어떻게 하면 "http://juclass.co.kr"로 접속했을 때 "http://www.juclass.co.kr"로 바꿀 수 있을지 도전해 보자.

 

 

2. 로드밸런서에서 "example.com"으로 들어오는 요청은 "www.example.com"으로 변경해서 인스턴스로 전달하기

 

일단 2번 방법을 다시 진행해 보기로 했다.

 

먼저 EC2에 로드밸런서를 설정해 주자.

 

 

Application Load Balancer를 선택해 주고 아래 설정파일들을 작성해 보자.

 

 

나는 https:// 를 설정하지 않았기 때문에 무조건 80 포트로 요청이 들어올 것이니 80 포트 리스너와 대상그룹을 생성해 주자.

 

 

위 HTTP 80은 인스턴스의 포트

 

 

다음을 눌러서 대상 등록을 해줄 건데, 나의 인스턴스 80 포트와 Route 53 DNS의 80 포트를 연결해 줄 것이다.

하단의 포트는 Route53 DNS의 80 포트입니다.

 

 

'아래에 보류 중인 것으로 포함'을 눌러서 대상 그룹 생성

 

 

이제 대상 그룹을 로드밸런서에 연결해 줍시다.

 

 

생성된 로드밸런서를 봅시다

 

 

 

상태가 프로비저닝 중이니까 기다렸다가 다시 진행합니다

 

프로비저닝이 완료되면 로드밸런서를 Route53 DNS A 레코드에 연결해 줍시다. 이전에 만들었던 레코드를 변경해 봅시다

 

두 레코드 모두 변경 후 확인을 해보면 접속이 잘 이루어지고, EC2 nginx access.log에도 제대로 출력되는 것을 볼 수 있다.

 

 

 

 

이제 로드밸런서를 이용해서 2개의 URL이 접속되는 것을 확인했다. 이제 로드밸런서의 리스너에 규칙을 추가해서 "http://juclass.co.kr"로 들어오는 요청은 "http://www.juclass.co.kr"로 보내도록 하자

 

참고 사이트: https://repost.aws/ko/knowledge-center/elb-redirect-to-another-domain-with-alb

 

Application Load Balancer를 사용하여 한 도메인을 다른 도메인으로 리디렉션

Application Load Balancer를 사용하여 한 도메인을 다른 도메인으로 리디렉션하려고 합니다.

repost.aws

 

로드밸런서 리스너에 들어가 리스너 규칙 추가를 눌러주자

 

 

알아볼 수 있는 이름 설정해 두고,

 

 

규칙 조건을 정의한다.

 

 

내가 해야 할 건 호스트 헤더를 변경하는 것이기 때문에, 호스트 헤더를 선택하고, 어떤 조건이 들어왔을 때 실행할지 입력한다.

나는 "juclass.co.kr"로 들어오는 요청을 "www.juclass.co.kr"로 변경할 것이기 때문에 아래와 같이 설정했다.

 

 

IF 조건을 추가했다면, THEN 블럭을 만들어야 하는데, 나는 호스트 헤더를 변경해야 하기 때문에, URL로 리디렉션을 선택했고, 호스트의 내용만 수정했다. 나머지는 그대로 두면 된다고 AWS DOC에 그렇게 적혀있다.

 

 

규칙 우선순위를 설정하는데, 우선순위는 100 단위로 설정하는 것이 좋다고 한다. 규칙 우선순위는 무조건 숫자가 작은 것을 먼저 실행하게 된다.

 

 

이제 설정한 규칙대로 진행해 보면, "http://juclass.co.kr"로 접속하는 요청은 301 Moved Permanantly가 발생하고 "http://www.juclass.co.kr"로 url이 이동된 것을 볼 수 있다!!

 

 

근데 nginx access.log에 엄청 무차별적인 요청이 들어오고 있는데 이건 도대체 뭘까..

 

 

이건 error.log --> 보니까 잘 막고 있는 것 같은데..?

 

 

해답: 해당 요청은 봇으로 인한 공격이라고 한다. 흔한 공격이라고 하는데, 내가 보안그룹에서 모든 트래픽 허용으로 해두어서 그런 것 같다. 

 


3. Ngnix에서 "example.com"으로 들어오는 요청에 대해서 Host를 "www.example.com"로 변경해 return 해주기

 

기본적인 애플리케이션 서버는 앞단에 Nginx가 설치되어 있어서 nginx에서 요청을 잡아 처리할 수 있다. 여기서 nginx.conf 파일에서 

'juclass.co.kr' 경로를 잡아, 루트 경로부터 접속되는 모든 요청의 Host를 변경해 주려고 한다.

# 기본 nginx 설정 파일
server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

 

일단 시작하기 앞서, 로드밸런서에 설정했던 규칙을 제거해 주자.

 

로드밸런서 규칙을 제거하면 로딩되는 시간이 조금 걸리는 것 같다. 아까 처음 설정할 때도 꽤나 시간이 걸렸는데 왜 이렇게 오래 걸리는지 모르겠다.. 일단 로드밸런서 규칙을 제거하면 "juclass.co.kr"로 접속했을 때 "www.juclass.co.kr"로 redirect가 되지 않을 것이다.

 

 

예상대로 redirect가 되지 않는 것을 확인했으니 이제 nginx에서 redirect 시켜보자!!

 

nginx 설정을 변경해 주고 nginx reload를 해주자

# 기본 nginx 설정 파일
server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

		# 해당 부분 추가!!        
        location / {
            return 301 http://www.juclass.co.kr$request_uri;
        }

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

 

:wq 후 sudo systemctl reload nginx 명령 수행!

 

음 redirect는 되는데 에러가 발생한다.

nginx access.log를 봐도 한 번 새로고침에 엄청난 request를 만들어낸다. 무슨 일인지 알아보자.

 

 

먼저 개발자 도구를 확인해 보니 redirect가 많이 일어나고 있다.

nginx 설정을 잘 생각해 보니.. server_name를 지정해 주지 않았다. 도메인 이름을 명시하지 않아서 Nginx에서 모든 호스트 이름에 대응하는 와일드카드로 설정되어 있었다. 나는 "jucalss.co.kr" 요청이 들어오는 것에 대해서만 "www.juclass.co.kr"로 변경해 주면 되고, 그 이외에는 "www.juclass.co.kr" 호스트 블럭에서 잡아야 한다는 것을 깜빡했다.

...
	server_name  _;
...

 

그래서 아래 코드처럼 수정하면 nginx에서 잘 잡을 수 있을 거라 생각한다.

server {
    listen 80;
    server_name juclass.co.kr;

    # juclass.co.kr으로 들어오는 요청을 www.juclass.co.kr로 리디렉션
    return 301 http://www.juclass.co.kr$request_uri;
}

server {
    listen 80;
    server_name www.juclass.co.kr;

    # www.juclass.co.kr로 들어온 요청을 처리
    root /usr/share/nginx/html;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;
    location = /404.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
}

 

"juclass.co.kr"로 입력했을 때 "www.juclass.co.kr"로 redirect 된 것을 확인할 수 있다..!!!

 

근데 사실 Nginx에서 redirect 하는 것이 좋은지, 로드밸런서에서 redirect 하는 것이 나은지 아직 잘 모르겠다.

 

이건 추후 공부하도록 하자 ㅎㅎ

 

cross-origin frame 에러는 이런 방식으로 해결하면 될 것 같다. 근데 나도 아직 뭐가 맞는건지 잘 모르겠다. 휴..

 

✌🏻결론: 아직 뭐가 더 좋은지는 모르겠지만 일단 호스트 도메인을 변경하는 것에는 성공했다.

 

728x90
반응형