[해결됨] 외부의 Rest API가 웹프로젝트에서만 403 떨어지는데요. 도와주세요 ㅠ

안녕하세요.
외부의 API를 웹프로젝트 서버단에서 호출하여 결과값을 받아오고자 하는데요.
해당 API는 Postman, 콘솔프로젝트, curl로 호출할때는 정상적으로 200 결과값이 받아집니다.

딱 웹서버단에서 호출하면 403 forbidden 이 떨어지는데요. 이런 경우 무엇을 확인해 봐야 할까요?
처음엔 도메인이 달라서 브라우저 단에서 차단(CORS)되는건 아닌가 싶었는데 그건 클라이언트와 연관있
는 부분이라 제가 하려는건 서버단에서 호출이라 해당이 안되는 것 같습니다.

호출하려는 API는 GET 방식의 “http://api.eu.safenetid.com/api/v1/healthcheck” 주소이며
인증이나 다른 헤더 등을 포함하지 않아도 거의 호출 됩니다.

우선 제가 해본 코드 입니다.
CMD 창에서 CURL로 호출해본 결과 정상적으로 결과가 떨어집니다.
image

다음으로 리눅스에서도 CURL로 호출해본 결과
image

다음은 Postman에서 특별한 설정 없이 Method와 주소만 입력하고 날려본 결과 입니다.
image

다음은 Postman에서 생성해준 C# 코드로 콘솔에서 호출해서 날려본 결과입니다.
image

해당 콘솔의 코드 입니다.

using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace ConsoleApp41
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            CallApi().GetAwaiter().GetResult();
        }

        static async Task CallApi()
        {
            var client = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Get
                , "http://api.eu.safenetid.com/api/v1/healthcheck");
            var response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            Console.WriteLine(await response.Content.ReadAsStringAsync());
        }
    }
}

asp.net core 3.1 API 프로젝트로 생성하여 동일 코드를 날리면 다음과 같이 403으로 오류가 납니다.
image

해당 코드 입니다.

using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using System.Threading.Tasks;

namespace WebApplication25.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {

        [HttpGet]
        public async Task<string> GetHC()
        {
            var client = new HttpClient();
            var request = new HttpRequestMessage(HttpMethod.Get
                , "http://api.eu.safenetid.com/api/v1/healthcheck");
            var response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync();
        }
    }
}

검색을 해보면 Header 값에 User-Agent 등을 설정해라. 뭐라 여러 건들이 나오는데 제가 궁금한건
Postman, Curl, 콘솔 프로젝트는 다 제대로 호출이 되는데 왜 웹서버 쪽에서만 호출하면 403이 발생하는지에 대한 의문입니다. 어떤 부분을 의심해 볼 수 있을지 고수님들의 조언 부탁드립니다.
질문 읽어주셔서 감사합니다.

해결 내용-------------------------------------------------------------------------------------------------------
문제는 asp.net core 3.1에서 403 Forbidden이 확인되었고 asp.net core 6.0에서는 문제가 없었습니다.
두 버전의 차이점을 확인하고자 burp suite를 통해 request를 잡아 내용을 확인한 결과 차이가 있었습니다.

asp.net 3.1
GET /api/v1/healthcheck HTTP/2
Host: api.eu.safenetid.com
Request-Id: |fa85aac-44305dc74956a676.

asp.net 6.0
GET /api/v1/healthcheck HTTP/2
Host: api.eu.safenetid.com
Traceparent: 00-186e08364a0e7409da9a2b72d1d8f2ef-592abf225052ace9-00

3.1과 6.0이 보내는 값이 약간 차이가 있더군요.
어떠한 헤더도 추가하지 않은 상태에서 Request-Id, Traceparent 등이 ASP.NET 에서 자체생성(?)하는 값인거 같은데요. 3.1에서의 Request-Id의 형식이 문제가 되는거 같습니다.
맨 앞의 | 와 끝의 . 이런것들에 의해 서버측 유효성에서 실패하는것으로 보여지네요.
Request-Id를 헤더에 임의로 생성해서 보내면 3.1에서도 정상으로 값이 나옵니다.

asp.net에서 결국 임의의 header등을 기본으로 추가하는거 같은데 이런 값들이 추가되지 않게 하는 옵션이 있지 않을까 싶습니다. 찾아봐야 겠네요.

1 Like

해당 웹서버가 말그대로 거부된 것으로 보입니다. 정확한 테스트를 위해 동일 환경의 다른 IP의 서버에서 테스트 해보시겠어요?

(여담으로 여러번 질의를 하니 429 오류가 뜨는 것으로 보아 관련된 처리가 된 API 서버인 듯 하네요)

1 Like

네 한번 확인해 보겠습니다.
저 API를 호출하는 환경은 비주얼 스튜디오의 개발환경에서 localhost에서 외부로 날리는 부분입니다.
다만 Postman과 curl, console 프로젝트에서 호출하는 API도 다 같은 PC에서 호출이라 해당 IP 등이 막히면 같이 403이 떠야 할 거 같은데 말이죠. ㅠㅠ
정말 이 내용 때문에 3일 동안 검색을 하는데 도통 해결을 못하겠네요. 답변 감사합니다.

1 Like

api 주소가 핸드폰에서 접속되는거 보니
코드가 잘못된거 같습니다.

호출 옵션등이 빠진거 같습니다.

2 Likes

개발환경의 localhost라 하셔서 간단히 프로젝트 템플릿으로 웹 API 프로젝트를 생성 후 동일코드로 확인하였는데 됩니다.

image

환경적인 문제일 듯 싶은데요 ^^; 어쨌든 됩니다.

3 Likes

아… 되셨나요? 확인 감사합니다~.
그래도 우선은 다행입니다. 환경적인 부분만 찾아서 고치면 될 듯 한데.
열심히 찾아보겠습니다. 다시 한번 감사합니다.

3 Likes

우등 당근님 화이팅!

2 Likes

제가 해보니 정상 동작합니다.

image

        public async Task<string> ApiCall()
        {
            var request = new HttpRequestMessage(HttpMethod.Get
                , "http://api.eu.safenetid.com/api/v1/healthcheck");

            var client = new HttpClient();
            var response = await client.SendAsync(request);
            response.EnsureSuccessStatusCode();

            return await response.Content.ReadAsStringAsync();
        }

콘솔과 웹 어플리케이션에서 동일한 결과를 출력합니다.
웹앱은 IIS 프록시 설정하나 안 하나 동일합니다.

API 가 forbid 하는 이유를 스스로 밝히지 않는 한, 어떤 규칙으로 forbid하는 지 알 수 있는 수단은 없습니다.

그래도, 유추라도 해 보려면, 클라이언트와 API 사이에 중간 서버(요청을 받아 API에 접속하고, 수신한 데이터를 클라이언트에게 전달)를 하나 더 작성하고, 그 서버에 HttpLogging 을 설정해서, 수신한 요청에 대한 로그를 남기도록 하는 방법이 최선일 것 같습니다.

클라이언트(콘솔, 포스트맨, 웹어플리케이션)의 요청을 받은 중간 서버가 남긴 로그 기록을 통해 각 요청이 어떻게 다른 지 확인하는 방식으로 하는 것이죠.

운이 좋아 문제가 있는 웹어플리케이션이 보낸 요청이 포스트맨/콘솔앱이 보낸 요청과 다른 점을 발견한다면 Forbid 사유를 유추할 수 있을 것이고, 없다면 여전히 알 수 없는 것이죠.

4 Likes

답변 감사합니다~.
네 번거로울텐데 직접 확인까지 해주시고 감사합니다.
하나하나 날려보면서 확인해 보겠습니다. 이제는 오기가 생기네요.

2 Likes

답변 감사합니다~.
내 여러 각도로 테스트 하는 중인데 현재는
Asp.Net Core 3.1 일때는 403 떨어지고 6.0 으로 하니 정상으로 출력 되는걸 확인했습니다.

3 Likes

방근 확인한 내용인데요. 이제껏 프로젝을 asp.net Core 3.1 로 생성해서 확인했었는데 이때는 403이 나왔는데 방금 asp.net Core 6.0 으로 하니 정상으로 출력 되는걸 확인했습니다.
닷넷 코어 버전에 따른 차이가 있는지 모르겠네요. 음.

3 Likes

방근 확인한 내용인데요. 이제껏 프로젝을 asp.net Core 3.1 로 생성해서 확인했었는데 이때는 403이 나왔는데 방금 asp.net Core 6.0 으로 하니 정상으로 출력 되는걸 확인했습니다.
닷넷 코어 버전에 따른 차이가 있는지 모르겠네요. 음.

3 Likes

8.0 이 목전에 있는데 3.1은 좀 심하셨네요. ^^

2 Likes

HTTP 기본 버전을 확인해 보시겠어요? HTTP/1.0을 거부하는 것일수도 있습니다. 외부라 제가 확인은 못하겠네요.

3 Likes

질문을 성의있게 잘 작성하시니까 답변 도 질문도 훌륭하네요 ^^

3 Likes

burp suite로 Request를 확인한 결과

asp.net 3.1
GET /api/v1/healthcheck HTTP/2
Host: api.eu.safenetid.com
Request-Id: |fa85aac-44305dc74956a676.

asp.net 6.0
GET /api/v1/healthcheck HTTP/2
Host: api.eu.safenetid.com
Traceparent: 00-186e08364a0e7409da9a2b72d1d8f2ef-592abf225052ace9-00

보내는 값이 약간 차이가 있더군요.
ASP.NET 3.1에서 자체생성(?)하는 Request-Id의 형식이 문제가 되는거 같습니다.
맨 앞의 | 와 끝의 . 이런것들에 의해 서버측 유효성에서 실패하는것으로 보여지네요.
Request-Id를 헤더에 임의로 생성해서 보내면 3.1에서도 정상으로 값이 나옵니다.

2 Likes

burp suite로 Request를 확인한 결과

asp.net 3.1
GET /api/v1/healthcheck HTTP/2
Host: api.eu.safenetid.com
Request-Id: |fa85aac-44305dc74956a676.

asp.net 6.0
GET /api/v1/healthcheck HTTP/2
Host: api.eu.safenetid.com
Traceparent: 00-186e08364a0e7409da9a2b72d1d8f2ef-592abf225052ace9-00

보내는 값이 약간 차이가 있더군요.
ASP.NET 3.1에서 자체생성(?)하는 Request-Id의 형식이 문제가 되는거 같습니다.
맨 앞의 | 와 끝의 . 이런것들에 의해 서버측 유효성에서 실패하는것으로 보여지네요.
Request-Id를 헤더에 임의로 생성해서 보내면 3.1에서도 정상으로 값이 나옵니다.

2 Likes

네 저희도 올리고 싶은데 시간을 안주네요. ㅠㅠ

1 Like

그만큼 절박한 심정으로다가…
제 마음이 느껴지시나요? ㅋㅋㅋ

1 Like

훌륭하십니다. :clap: :clap: :clap:

튜토리얼/팁 게시판에서 원인과 해결 과정이 공유되기를 희망합니다.

3 Likes