Uvicorn_server에서 IP 주소 범위(CIDR 표기법)로 접근을 차단하고 싶습니다. 채택완료

  Localhost에 아파치(2.4.52)와 그누보드6(6.0.4)실서비스를 이용하고 있습니다.

 

아파치(httpd.conf)에서는 디렉터리별로 특정 IP_대역(CIDR 표기법)을 차단하고 있습니다.

 

Uvicorn에서는 FastAPI 미들웨어로 차단해야 한다는 조언(이전 질문의 답글)에 따라,

 

/core/middleware.py

Copy
"""애플리케이션에 사용되는 미들웨어를 정의합니다."""

from user_agents import parse

 

from fastapi import FastAPI, Request, HTTPException

from fastapi.middleware.cors import CORSMiddleware

from starlette.middleware.base import BaseHTTPMiddleware

from starlette.middleware.sessions import SessionMiddleware

 

from core.plugin import (

    register_plugin_admin_menu, get_plugin_state_change_time,

    read_plugin_state, cache_plugin_state, cache_plugin_menu, register_plugin,

    unregister_plugin, delete_router_by_tagname

)

from core.settings import settings

 

    # glitter

import ipaddress

 

def regist_core_middleware(app: FastAPI) -> None:

    """애플리케이션에 아래 미들웨어를 추가합니다.

 

    미들웨어의 실행 순서는 코드의 역순으로 실행됩니다.

    - main.py의 main_middleware()보다 먼저 실행됩니다.

    """

 

    # 기본으로 실행되는 core 미들웨어를 추가합니다.

    @app.middleware("http")

.

.

    # glitter 차단할 IP 대역 목록

    blocked_ips = ["47.128.0.0/16", "185.0.0.0/8", "85.0.0.0/8"]

 

    # glitter IP 제한 미들웨어를 FastAPI 애플리케이션에 추가

    app.add_middleware(IPBlockMiddleware, blocked_ips=blocked_ips)

.

.

    # glitter Class_Middleware - start

class IPBlockMiddleware(BaseHTTPMiddleware):

    def __init__(self, app: FastAPI, blocked_ips: str):

        super().__init__(app)

        self.blocked_network = ipaddress.ip_network(blocked_ips)

 

    async def dispatch(self, request: Request, call_next):

        client_ip = ipaddress.ip_address(request.client.host)

        if client_ip in self.blocked_network:

            raise HTTPException(status_code=403, detail="Forbidden: Access is denied by m.Glitter.kr.")

        response = await call_next(request)

        return response

 

    # FastAPI 애플리케이션 인스턴스 생성

    app = FastAPI()

 

    @app.get("/")

    async def read_root():

        return {"message": "Welcome to the FastAPI application!"}

        # glitter Class_Middleware - end

.

.

클래스_미들웨어(IPBlockMiddleware)를 추가하고 

 

regist_core_middleware 함수안에 

 

app.add_middleware(IPBlockMiddleware, blocked_ips=blocked_ips)를 추가하였으나, ㅠ ㅠ .

 

제가 python 언어를 잘 모르는 지라, IP 접근을 막지 못하고 있습니다.

 

                       = = = 조언 부탁드립니다  = = =

 

-  Localhost 정보는 아래와 같습니다.

Copy
root@HumanpcNAS:~# uname && uname -r
Linux
6.1.20-efm-standard
.
root@HumanpcNAS:~# python3 -V
Python 3.9.9
.
root@HumanpcNAS:~# cat requirements.txt
.
fastapi>=0.111.0
.
root@HumanpcNAS:~# httpd -v
Server version: Apache/2.4.52 (Unix)
.

 

 

답변 2개

채택된 답변
+20 포인트

978180634_1717546166.3466.gif

 

테스트를 해보니 잘 됩니다.

 

다만, 해당 미들웨어.py 수정 하게 되면, 추후 공식 업데이트 내용을 덮어 씌울 경우 삭제되므로 해당 내용에 참고하시길 바랍니다.

 

middleware.py 파일을 열어주세요

 

4번 라인에

Copy
from fastapi import FastAPI, Request 

코드를 다음과 같이 수정 해주세요


from fastapi import FastAPI, Request, HTTPException

 

그리고 8번 라인에 다음을 추가 해주세요

Copy
from ipaddress import ip_network, ip_address

 

다음 block_ip 함수를 추가 해주세요 저는 18번 라인에 적용했습니다.

Copy
async def block_ip(request: Request):
    client_ip = request.client.host
    blocked_ips = ["127.0.0.11", "203.0.113.0/24"]  # 차단하려는 IP 대역을 여기에 추가

    for blocked_ip in blocked_ips:
        if ip_address(client_ip) in ip_network(blocked_ip):
            raise HTTPException(status_code=403, detail="Forbidden")

 

마지막으로 미들웨어 실행될 때 해당 함수를 호출 해주세요 37번 라인에 추가 해주세요

Copy
await block_ip(request)

 

위치가 잘 모르겠다 하시면 아래 스샷 빨간색 부분 참조하시길 바랍니다.

 

978180634_1717545994.7592.png

 

로그인 후 평가할 수 있습니다

답변에 대한 댓글 6개

-
- 안녕하세요
-
- 귀중한 시간을 내어주셔서 감사합니다.
-
- 초보의 주먹구구식 질문에 자세한 조견을 주셔서, 맹인이라도 해결할 것 같습니다.
-
- 바로 시도해 보겠습니다.
-
- . . . . . . . . .
.
.
.
- 작성하여주신 함수_미들웨어를 18번 줄에 놓았습니다.
[code]
async def block_ip(request: Request):
client_ip = request.client.host
blocked_ips = ["211.235.72.125", "47.128.0.0/16", "85.0.0.0/8", "185.0.0.0/8"] # 차단하려는 IP 대역을 여기에 추가

for blocked_ip in blocked_ips:
if ip_address(client_ip) in ip_network(blocked_ip):
raise HTTPException(status_code=403, detail="Forbidden")
[/code]
-
- 차단한 "211.235.72.125"가 Uvicorn_server 접속에 HTTP_200_OK를 받습니다. ㅠ ㅠ
[code]
root@HumanpcNAS:/mnt/VOL1/apache/_logs# cat m.glitter.kr_access_log.20240605
.
.
211.235.72.125 - - [05/Jun/2024:13:51:00 +0900] "GET / HTTP/1.1" 200 45383
211.235.72.125 - - [05/Jun/2024:13:51:06 +0900] "GET / HTTP/1.1" 200 45383
211.235.72.125 - - [05/Jun/2024:13:51:11 +0900] "GET / HTTP/1.1" 200 45383
211.235.72.125 - - [05/Jun/2024:13:51:52 +0900] "GET / HTTP/1.1" 200 45383
.
[/code]
-
- 제가 뭘~ 잘못한 것인가요?
-
- 아래의 구글_크롤러가 /bbs/qalist에 접근 못하듯이 접근제한(403)을 당하지 않는군요.
[code]
34.64.82.64 - - [05/Jun/2024:13:54:15 +0900] "GET /bbs/qalist HTTP/1.1" 403 4800
[/code]
-
- ㅠ ㅠ
-
37번 라인도 추가 해주신거죠 ??
-
- 네 ~~
[code]
# 기본으로 실행되는 core 미들웨어를 추가합니다.
@app.middleware("http")
async def core_middleware(request: Request, call_next):
await block_ip(request)
if not await should_run_middleware(request):
return await call_next(request)

# 플러그인 설정
[/code]
근데 생각해보면, 그누6 자체 기본 설정에 접근 / 차단 ip 설정하는 기능이 있습니다

관리자 > 기본환경 설정 > 접근가능 IP / 접근차단 IP
-
- 그런데 관리자 설정에서는 CIDR 표기로 IP 블럭을 제한할 수는 없군요
-
123.123.+ 도 입력 가능. (엔터로 구분)

이렇게 입력하시면 대역으로 됩니다.

댓글을 작성하려면 로그인이 필요합니다.

    ※ 필자는 다음과 같이 해결하였다.

 

      == main.py 수정 사항 ==

!. ip_address 모듈을 사용하여 Server의 main_middleware에

다음의 소스를 추가하는 방법을 사용하였다.

 

!. 특정 IP_대역(CIDR 표기법)을 차단하여 특정 페이지로 리딜렉션시키는 방법으로

  어떤 소스도 터치하지 못하게 한다.

 

!. main.py에 추가된 소스 -

Copy
import httpx

import aiohttp

.

from ipaddress import ip_network, ip_address

.

from fastapi.responses import  PlainTextResponse, StreamingResponse

.

.

.

    # 데이터베이스 설치여부 체크 == 필히, 이 주석 밑에 놓으세요.

    blocked_ip_ranges = ["195.2.67.0/24", "47.128.0.0/16", "85.0.0.0/8", "185.0.0.0/8", "211.235.72.120"]

    current_ip = ip_address(get_client_ip(request))

 

    for ip_range in blocked_ip_ranges:

        if current_ip in ip_network(ip_range):

            return RedirectResponse(url="http://115.23.70.228", status_code=303)

    ☆ 위의 소스 6줄은 main_middleware 바로 위에 놓을 것 -

 

★ return RedirectResponse(url="http://115.23.70.228", status_code=303), = 리다이렉트 소스 활용.

로그인 후 평가할 수 있습니다

댓글을 작성하려면 로그인이 필요합니다.

답변을 작성하려면 로그인이 필요합니다.

로그인
🐛 버그신고