IT

UserAgentの偽装を試せるDocker環境を用意してみた

はじめに

以下の記事にこんなコメントがありました。

UA ブロック程度で拒否できるほど生成 AI 事業者って技術レベル低いのかな?
Python かじればすぐ分かるけど、その程度ならすぐ対応できると思うよ。

コメントより

UA の偽装はやってみたことがないので、「試せる環境が欲しいな!」と思って以下の Docker 環境を用意しました。(後述)

ちなみに UA 偽装はわりと簡単にできました。

最近、有名な企業の Bot によるサイトダウンの事例を聞くことが多いですが、もしかしたら Bot 名もバンバン偽装されているのかもしれませんね。

利用するファイル情報

  • ディレクトリ構造
.
├── app
│   ├── Dockerfile
│   └── app.py
├── compose.yml
└── nginx
    ├── Dockerfile
    ├── conf.d
    │   └── default.conf
    └── logs //コマンド実行後に作成される
        ├── access.log
        └── error.log
  • 利用するファイル
# compose.yml
services:
  nginx:
    build:
      context: ./nginx
      dockerfile: Dockerfile
    ports:
      - "8080:80"
    volumes:
      - ./nginx/logs:/var/log/nginx
      - ./nginx/conf.d:/etc/nginx/conf.d
    depends_on:
      - app

  app:
    build:
      context: ./app
      dockerfile: Dockerfile
    expose:
      - "5000"

# ./nginx/Dockerfile
FROM nginx:alpine

RUN mkdir -p /var/log/nginx
RUN touch /var/log/nginx/access.log /var/log/nginx/error.log

# ./nginx/conf.d/default.conf
server {
    listen 80;
    server_name localhost;

    access_log /var/log/nginx/access.log combined;
    error_log /var/log/nginx/error.log;

    location / {
        proxy_pass http://app:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header User-Agent $http_user_agent;
    }
}

# ./app/Dockerfile
FROM python:3.12-slim

WORKDIR /app
COPY . /app

RUN pip install flask

EXPOSE 5000
CMD ["python", "app.py"]

# ./app/app.py
from flask import Flask, request
import json

app = Flask(__name__)

@app.route('/')
def index():
    user_agent = request.headers.get('User-Agent')
    response = {
        'user_agent': user_agent,
        'headers': dict(request.headers)
    }
    return json.dumps(response, indent=2)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
  • 利用するコマンド

docker-compose up --build


アクセス結果

上記で起動したサーバーhttp://localhost:8080に対してのアクセス結果を記載します。

ブラウザアクセス:safari 18.3

  • ブラウザ上の表示
{
	"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Safari/605.1.15",
	"headers": {
		"Host": "localhost",
		"X-Real-Ip": "172.19.0.1",
		"X-Forwarded-For": "172.19.0.1",
		"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Safari/605.1.15",
		"Connection": "close",
		"Sec-Fetch-Dest": "document",
		"Upgrade-Insecure-Requests": "1",
		"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
		"Sec-Fetch-Site": "none",
		"Sec-Fetch-Mode": "navigate",
		"Accept-Language": "ja",
		"Priority": "u=0, i",
		"Accept-Encoding": "gzip, deflate"
	}
}
  • Nginx のアクセスログ
172.19.0.1 - - [22/Feb/2025:05:42:59 +0000] "GET / HTTP/1.1" 200 729 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Safari/605.1.15"

ブラウザアクセス:Chrome 133.0.6943.127

  • ブラウザ上の表示
{
	"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
	"headers": {
		"Host": "localhost",
		"X-Real-Ip": "172.19.0.1",
		"X-Forwarded-For": "172.19.0.1",
		"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
		"Connection": "close",
		"Sec-Ch-Ua": "\"Not(A:Brand\";v=\"99\", \"Google Chrome\";v=\"133\", \"Chromium\";v=\"133\"",
		"Sec-Ch-Ua-Mobile": "?0",
		"Sec-Ch-Ua-Platform": "\"macOS\"",
		"Upgrade-Insecure-Requests": "1",
		"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
		"Sec-Fetch-Site": "none",
		"Sec-Fetch-Mode": "navigate",
		"Sec-Fetch-User": "?1",
		"Sec-Fetch-Dest": "document",
		"Accept-Encoding": "gzip, deflate, br, zstd",
		"Accept-Language": "ja,en-US;q=0.9,en;q=0.8"
	}
}
  • Nginx のアクセスログ
172.19.0.1 - - [22/Feb/2025:05:43:50 +0000] "GET / HTTP/1.1" 200 980 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"

ブラウザアクセス:Googlebot 偽装(やり方は後述リンク参照)

  • ブラウザ上の表示
{
	"user_agent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
	"headers": {
		"Host": "localhost",
		"X-Real-Ip": "172.19.0.1",
		"X-Forwarded-For": "172.19.0.1",
		"User-Agent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
		"Connection": "close",
		"Upgrade-Insecure-Requests": "1",
		"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
		"Sec-Fetch-Site": "none",
		"Sec-Fetch-Mode": "navigate",
		"Sec-Fetch-User": "?1",
		"Sec-Fetch-Dest": "document",
		"Accept-Encoding": "gzip, deflate, br, zstd",
		"Accept-Language": "ja,en-US;q=0.9,en;q=0.8"
	}
}
  • Nginx のアクセスログ
172.19.0.1 - - [22/Feb/2025:05:35:31 +0000] "GET / HTTP/1.1" 200 744 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

Curl でのチェック

{
  "user_agent": "curl/8.7.1",
  "headers": {
    "Host": "localhost",
    "X-Real-Ip": "172.19.0.1",
    "X-Forwarded-For": "172.19.0.1",
    "User-Agent": "curl/8.7.1",
    "Connection": "close",
    "Accept": "*/*"
  }
}
  • Nginx のアクセスログ
172.19.0.1 - - [22/Feb/2025:05:29:25 +0000] "GET / HTTP/1.1" 200 224 "-" "curl/8.7.1"

UA を偽装したCurl

curl -A "Custom User Agent" http://localhost:8080

  • コンソール上の表示
{
  "user_agent": "Custom User Agent",
  "headers": {
    "Host": "localhost",
    "X-Real-Ip": "172.19.0.1",
    "X-Forwarded-For": "172.19.0.1",
    "User-Agent": "Custom User Agent",
    "Connection": "close",
    "Accept": "*/*"
  }
}
  • コンソール上の表示 Nginx のアクセスログ
172.19.0.1 - - [22/Feb/2025:05:44:45 +0000] "GET / HTTP/1.1" 200 238 "-" "Custom User Agent"

UA 偽装で参考にした記事

最後に

UA 偽装用に用意しましたが、普通に UA チェック用で利用できますね。

またUAに依存するようなシステム構成のリスクがわかり個人的に有益な経験でした。

Bot対策としてはaws等がマネージドなサービスを(WAF系)を提供しているので、積極的に利用していきたいですね。

以上、どなたかのお役に立てば幸いです。

  • この記事を書いた人

緑川縁

ニートからシステムエンジニアになった人
クラウド案件をメインにやっています。
保持資格:CCNA,AWS SAA&SAP,秘書検定2級
趣味でボカロ曲作り始めました。

-IT
-, ,