테스트 사이트 - 개발 중인 베타 버전입니다

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

glitter0gim 1년 전 조회 1,225

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

 

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

 

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

 

/core/middleware.py

</p>

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

<p>from user_agents import parse</p>

<p> </p>

<p>from fastapi import FastAPI, Request, HTTPException</p>

<p>from fastapi.middleware.cors import CORSMiddleware</p>

<p>from starlette.middleware.base import BaseHTTPMiddleware</p>

<p>from starlette.middleware.sessions import SessionMiddleware</p>

<p> </p>

<p>from core.plugin import (</p>

<p>    register_plugin_admin_menu, get_plugin_state_change_time,</p>

<p>    read_plugin_state, cache_plugin_state, cache_plugin_menu, register_plugin,</p>

<p>    unregister_plugin, delete_router_by_tagname</p>

<p>)</p>

<p>from core.settings import settings</p>

<p> </p>

<p>    # glitter</p>

<p>import ipaddress</p>

<p> </p>

<p>def regist_core_middleware(app: FastAPI) -> None:</p>

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

<p> </p>

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

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

<p>    """</p>

<p> </p>

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

<p>    @app.middleware("http")</p>

<p>.</p>

<p>.</p>

<p>    # glitter 차단할 IP 대역 목록</p>

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

<p> </p>

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

<p>    app.add_middleware(IPBlockMiddleware, blocked_ips=blocked_ips)</p>

<p>.</p>

<p>.</p>

<p>    # glitter Class_Middleware - start</p>

<p>class IPBlockMiddleware(BaseHTTPMiddleware):</p>

<p>    def __init__(self, app: FastAPI, blocked_ips: str):</p>

<p>        super().__init__(app)</p>

<p>        self.blocked_network = ipaddress.ip_network(blocked_ips)</p>

<p> </p>

<p>    async def dispatch(self, request: Request, call_next):</p>

<p>        client_ip = ipaddress.ip_address(request.client.host)</p>

<p>        if client_ip in self.blocked_network:</p>

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

<p>        response = await call_next(request)</p>

<p>        return response</p>

<p> </p>

<p>    # FastAPI 애플리케이션 인스턴스 생성</p>

<p>    app = FastAPI()</p>

<p> </p>

<p>    @app.get("/")</p>

<p>    async def read_root():</p>

<p>        return {"message": "Welcome to the FastAPI application!"}</p>

<p>        # glitter Class_Middleware - end</p>

<p>.</p>

<p>.</p>

<p>

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

 

regist_core_middleware 함수안에 

 

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

 

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

 

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

 

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

</p>

<p>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 포인트
1년 전

http://sir.kr/data/editor/2406/978180634_1717546166.3466.gif" width="100%" />

 

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

 

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

 

middleware.py 파일을 열어주세요

 

4번 라인에

</p>

<pre>
from fastapi import FastAPI, Request </pre>

<p>코드를 다음과 같이 수정 해주세요</p>

<pre>
from fastapi import FastAPI, Request, HTTPException</pre>

<p>

 

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

</p>

<pre>
from ipaddress import ip_network, ip_address</pre>

<p>

 

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

</p>

<pre>
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")</pre>

<p>

 

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

</p>

<pre>
await block_ip(request)</pre>

<p>

 

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

 

 

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

답변에 대한 댓글 6개

g
glitter0gim
1년 전
-
- 안녕하세요
-
- 귀중한 시간을 내어주셔서 감사합니다.
-
- 초보의 주먹구구식 질문에 자세한 조견을 주셔서, 맹인이라도 해결할 것 같습니다.
-
- 바로 시도해 보겠습니다.
-
- . . . . . . . . .
.
.
.
- 작성하여주신 함수_미들웨어를 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]
-
- ㅠ ㅠ
-
미니님a
1년 전
37번 라인도 추가 해주신거죠 ??
g
glitter0gim
1년 전
-
- 네 ~~
[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]
미니님a
1년 전
근데 생각해보면, 그누6 자체 기본 설정에 접근 / 차단 ip 설정하는 기능이 있습니다

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

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

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

glitter0gim
1년 전

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

 

      == main.py 수정 사항 ==

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

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

 

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

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

 

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

</p>

<p>import httpx</p>

<p>import aiohttp</p>

<p>.</p>

<p>from ipaddress import ip_network, ip_address</p>

<p>.</p>

<p>from fastapi.responses import  PlainTextResponse, StreamingResponse</p>

<p>.</p>

<p>.</p>

<p>.</p>

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

<p>    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"]</p>

<p>    current_ip = ip_address(get_client_ip(request))</p>

<p> </p>

<p>    for ip_range in blocked_ip_ranges:</p>

<p>        if current_ip in ip_network(ip_range):</p>

<p>            return RedirectResponse(url="<a href="http://115.23.70.228"," target="_blank" rel="noopener noreferrer">http://115.23.70.228",</a> status_code=303)

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

 

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

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

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

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

로그인