[그누6실서비스]=Uvicorn_server에서 크롤러(crawler)를 차단할 방법을 알고 싶습니다.

[그누6실서비스]=Uvicorn_server에서 크롤러(crawler)를 차단할 방법을 알고 싶습니다.

QA

[그누6실서비스]=Uvicorn_server에서 크롤러(crawler)를 차단할 방법을 알고 싶습니다.

본문

Localhost에 아파치(2.4.52)와 그누보드6(6.0.3)실서비스(https://sir.kr/g6_tip?sca=&sfl=wr_subject&stx=%EA%B7%B8%EB%88%846%EC%8B%A4%EC%84%9C%EB%B9%84%EC%8A%A4)를 사용 중입니다.

 

그누보드6_설치_루트(DocumentRoot)에 robots.txt와 사이트맵(xxx.xml)을 업로드 하였으나,

 

읽히지 않는군요(https://policy.glitter.kr/qa_php/map_txt.png).

 

여러모로 노력하였으나, FastAPI 프레임워크를 모른체 범접한 이가 

 

Uvicorn_server에서 크롤러(crawler)를 차단하는 방법을 찾기란  쉽지 않습니다.

 

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

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.103.2
.
root@HumanpcNAS:~# httpd -v
Server version: Apache/2.4.52 (Unix)
.

 

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

이 질문에 댓글 쓰기 :

답변 2

몇가지 방법을 응용해서 한번 해보시겠어요..

 

1. FastAPI 미들웨어로 User-Agent 기반 차단

 

from fastapi import FastAPI, Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse

app = FastAPI()

class BlockCrawlerMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        user_agent = request.headers.get('user-agent', '')
        if 'crawler' in user_agent.lower() or 'bot' in user_agent.lower():
            return JSONResponse(status_code=403, content={"detail": "Access forbidden: Crawler detected"})
        response = await call_next(request)
        return response

app.add_middleware(BlockCrawlerMiddleware)

.get("/")
def read_root():
    return {"message": "Hello, world"}

.get("/robots.txt")
def get_robots_txt():
    return Response(content="User-agent: *\nDisallow: /", media_type="text/plain")
 

 

2. .htaccess 파일 설정 (Apache 서버)

 

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (crawler|bot) [NC]
RewriteRule ^ - [F,L]
</IfModule>
 

 

3. IP 차단

 

from fastapi import FastAPI, Request, HTTPException
from starlette.middleware.base import BaseHTTPMiddleware

app = FastAPI()

BLOCKED_IPS = ["192.168.0.1", "10.0.0.1"]

class BlockIPMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        client_ip = request.client.host
        if client_ip in BLOCKED_IPS:
            raise HTTPException(status_code=403, detail="Access forbidden: Your IP is blocked")
        response = await call_next(request)
        return response

app.add_middleware(BlockIPMiddleware)

.get("/")
def read_root():
    return {"message": "Hello, world"}
 

.
  안녕하세요

조언 감사합니다.

전문적인 조언을 받고 보니, 얼떨떨하지만 방법은 있군요 !

Python 언어를 모른르는 체 그누6을 사용하는 중입니다.

'제이앤'님의 전문적인 조언이 눈에 들어오지는 않으나,

소스를 몇 번이라도 읽어 보고, 구글링을 해서라도 해결해 보겠습니다.

.  .  .

> > >제 능력으로 감당하기엔 너무 professional response입니다. ㅠ ㅠ

  저의 능력으로 쉽게 접근할 수 없는 문제를 해결하려 한 듯합니다.

    감사합니다.
.

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

 

  == main.py 수정 사항 ==

!. Server의 특정 디렉터리에 robots.txt와 site_map.xml을 두고

  static  파일로 그누보드6에 마운트하는 방법을 사용하였다.

 

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


import httpx
import aiohttp
.
from ipaddress import ip_network, ip_address
.
from fastapi.responses import  PlainTextResponse, StreamingResponse
from fastapi.staticfiles import StaticFiles
.
.
.
ROBOTS_TXT_PATH = "/mnt/VOL1/hwi/m.robots.txt"
M_GLITTER_SITEMAP_PATH = "/mnt/VOL1/hwi/m.glitter_sitemap.xml"
FAVICON_ICO_PATH = "/mnt/VOL1/hwi/gimg/favicon/favicon.ico"
 
async def fetch_local_file(path: str, response_class=PlainTextResponse):
    if os.path.exists(path):
        with open(path, "rb") as file:
            content = file.read()
        if response_class == PlainTextResponse:
            return response_class(content.decode("utf-8", errors="ignore"))
        elif response_class == StreamingResponse:
            return response_class(iter([content]), media_type="application/octet-stream")
    else:
        return PlainTextResponse(f"{path} file not found", status_code=404)
 
.get("/robots.txt", include_in_schema=False)
async def robots_txt():
    return await fetch_local_file(ROBOTS_TXT_PATH)
 
.get("/m.glitter_sitemap.xml", include_in_schema=False)
async def m_glitter_sitemap():
    return await fetch_local_file(M_GLITTER_SITEMAP_PATH)
 
.get("/", response_class=HTMLResponse)
async def read_root():
    return """
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
 
    </head>
    <body>
        <h1>그누보드6 본문</h1>
    </body>
    </html>+
    """
 
.get("/favicon.ico", include_in_schema=False)
async def favicon():
    return await fetch_local_file(FAVICON_ICO_PATH, response_class=StreamingResponse)

☆ import 코드 이외의 코드(함수 5개)는 main_middleware 함수의 아래에, 

    regist_core_middleware(app) 위에; 즉 사이에 놓아야 한다.

 

☆ /mnt/VOL1/hwi/,  /mnt/VOL1/hwi/gimg/favicon/ 이 폴더들은 사용자 특정 폴더임.

   -그누보드6은 /mnt/VOL1/base2/에 설치됨.

 

!. uvicorn server를 재시작 - 사용자를 root로 가정한 명령어 임.


cd  <누보드6 설치 디렉토리("/mnt/VOL1/base2")로 변경>
systemctl daemon-reload
python -m venv venv
source venv/bin/activate
uvicorn main:app --reload --host 0.0.0.0 --port 8000

 

!. http://사용자 IP(DNS)/robots.txt , 이 URL의 실행 확인 -

 

★ 필자의 "/mnt/VOL1/hwi/m.robots.txt"은 이렇게( https://m.glitter.kr/robots.txt ) 마운트 되었다.


/mnt/VOL1/base2/ ( 그누보드6 )
│   ├── .env
│   ├── api/
│   ├── core/
│   ├── lib/
│   ├── service/
│   ├── venv/
│   ├── . . .
│   └── main.py
│
/mnt/VOL1/hwi/ ( static 파일 디렉터리 )
│   ├── gimg/
│   │   ├── img/
│   │   └── favicon/
│   ├── css/
│   │   ├── glitter.css
│   │   ├── m.glitter_default.css
│   │   ├── . . .
│   │   └── policy.glitter_default.css
│   ├── robots.txt
│   ├── m.robots.txt
│   ├── policy.robots.txt
│   ├── . . .
│   ├── glitter_sitemap.xml
│   ├── m.glitter_sitemap.xml
│   ├── policy.glitter_sitemap.xml
│   └── site_map.xml
│
답변을 작성하시기 전에 로그인 해주세요.
전체 180
QA 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT