広告削除プロキシ構築

はじめに

その昔かなり適当な広告削除プロキシの構築について記事を書いた.

heavymoon.hateblo.jp

以前の内容は RaspberryPi で適当に構築したときのメモレベルだったので,改めて見ると非常にわかりにくい.
諸事情により RaspberryPi プロキシ環境は解体して再構築したので記事内容を改める.

大まかな流れは以下.

  1. サーバ立てる
  2. プロキシ (squid, privoxy) と変換コマンドをインストールする
  3. フィルタ変換処理を実装する

構成イメージはこんな感じ.

The Internet
  ↕
┌─────────┐
│┌───────┐│
││privoxy││
│└───────┘│
│  ↕      │
│┌─────┐  │
││squid│  │
│└─────┘  │
└─────────┘
  ↕
ClientPC

サーバを立てる

ESXi 上に CentOS7 minimal を入れた.

細かい設定はお好みで.

プロキシ (squid, privoxy) と変換コマンドをインストールする

必要なものをインストールする.

$ sudo yum install squid.x86_64 privoxy.x86_64 https://s3.amazonaws.com/ab2p/adblock2privoxy-1.4.2-1.el7.centos.x86_64.rpm

変換コマンドには以下を利用する.

projects.zubr.me

squid

設定ファイル (/etc/squid/squid.conf) を書く.

ACLの設定とHTTPヘッダを少し変更する.
refresh_pattern はかなり昔に設定した名残.無くてもいいかも.

#######################################
# squid.conf
#######################################
## define ACL
acl localnet src $(LANのNWアドレス)/24
acl SSL_ports port 443          # HTTPS
acl Safe_ports port 21          # FTP
acl Safe_ports port 53          # DNS
acl Safe_ports port 80          # HTTP
acl Safe_ports port 123         # NTP
acl Safe_ports port 443         # HTTPS
acl Safe_ports port 500         # KIE for VPN
acl Safe_ports port 1025-65535  # unregistered ports
acl CONNECT method CONNECT
acl RHEL dstdomain .redhat.com

## set ACL
always_direct   allow   RHEL
http_access     deny    !Safe_ports
http_access     deny    CONNECT !SSL_ports
http_access     allow   localhost manager
http_access     deny    manager
http_access     allow   localhost
http_access     allow   localnet
http_access     deny    all

## Listen IP/Port
http_port $(自分のIPアドレス):3128

## Cascade Proxy
cache_peer $(自分のIPアドレス) parent 8118 0 proxy-only
never_direct allow all

## Proxy Config
coredump_dir /var/spool/squid
refresh_pattern ^ftp:               1440    20% 10080
refresh_pattern -i (/cgi-bin/|\?)   0       0%  0
refresh_pattern .                   0       20% 4320

## HTTP Header Config
visible_hostname    unknown
forwarded_for       off

## LOG FORMAT
logformat accesslog  %tl %6tr %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %mt
access_log daemon:/var/log/squid/access.log accesslog

privoxy

設定ファイル (/etc/privoxy/config) を書く.

フィルタ格納場所は /etc/privoxy/ab2p/ にしておく.
その他の設定は昔設定したままなのであんまり覚えてない.勝手に調べてくれ.

#######################################
# privoxy config
#######################################
## Process Config
confdir /etc/privoxy
listen-address $(自分のIPアドレス):8118

## Log File
logdir /var/log/privoxy
logfile privoxy.log

debug     1 # Log the destination for each request Privoxy let through. See also debug 1024.
debug   256 # debug GIF de-animation
debug   512 # Common Log Format
debug  1024 # Log the destination for requests Privoxy didn't let through, and the reason why.
debug  2048 # CGI user interface
debug  4096 # Startup banner and warnings.
debug  8192 # Non-fatal errors
debug 65536 # Log the applying actions

## Action File
actionsfile match-all.action
actionsfile default.action
actionsfile user.action
actionsfile ab2p/ab2p.system.action
actionsfile ab2p/ab2p.action

## Filter File
filterfile default.filter
filterfile user.filter
filterfile  ab2p/ab2p.system.filter
filterfile  ab2p/ab2p.filter

## Remote Control
toggle  1
enable-remote-toggle  0
enable-remote-http-toggle  0
enable-edit-actions 0

## Proxy Config
enforce-blocks 0
buffer-limit 4096
enable-proxy-authentication-forwarding 0
forwarded-connect-retries  0
accept-intercepted-requests 0
allow-cgi-request-crunching 0
split-large-forms 0
keep-alive-timeout 5
tolerate-pipelining 1
socket-timeout 300

フィルタ配置先ディレクトリは作成しておく.

$ sudo mkdir /etc/privoxy/ab2p

フィルタ変換処理を実装する

ファイル構成はとりあえずこんな感じ.

/opt/script/
├ ab2p.source # AdBlock用フィルタリスト
└ ab2p.sh  # フィルタ更新および変換処理

AdBlock用フィルタリスト

adblock用のフィルタは色々な人たちが作ってくれている.

wikiwiki.jp

お好みでフィルタのリスト (ab2p.source) を作成する.
私が選んだのは選んだのは以下の通り.結構昔に選んだもののままなのでもしかするとちょっと古いかも.

#################################
## https://280blocker.net/
#################################
https://280blocker.net/files/280blocker_adblock.txt

#################################
## http://tofukko.r.ribbon.to/abp.html
#################################
http://tofukko.r.ribbon.to/Adblock_Plus_list.txt

#################################
## http://qme.mydns.jp/adblock.html
#################################
http://qme.mydns.jp/data/AdblockV2.txt

#################################
## http://pokapoka.html.xdomain.jp/
#################################
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/mochi_filter.txt
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/mochi_filter_extended.txt
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/negi_filter.txt
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/kame_filter.txt
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/kotori_filter.txt
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/ichigo_filter.txt
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/kujira_filter.txt
https://raw.githubusercontent.com/eEIi0A5L/adblock_filter/master/tamago_filter.txt

#################################
## OTHERS
#################################
https://secure.fanboy.co.nz/easylist.txt

フィルタ更新および変換処理

処理の内容は大まかに以下の通り.

  1. AdBlock用フィルタを取得する
  2. AdBlockのフィルタをPrivoxy向けに変換して /etc/privoxy/ab2p に配置する
  3. 作成したファイルのバックアップ用に固める

そういえば minimal な CentOS だと wget が標準で入ってないのでインストールしておく必要がある.

#!/bin/bash
#######################################
# ab2p.sh
#######################################
## GlobalConfig #############
ScriptName=$(basename ${0})
ScriptPath=$(cd $(dirname ${0}) && pwd)
LogFile=/var/log/script/${ScriptName/.sh}.log

LogInfo () {
    echo "$(date '+%Y-%m-%d %T') [INFO] $@" | tee -a $LogFile
}
LogWarn () {
    echo "$(date '+%Y-%m-%d %T') [WARN] $@" | tee -a $LogFile
}
LogErr () {
    echo "$(date '+%Y-%m-%d %T') [ERR] $@" | tee -a $LogFile
    exit 1
}
LogDebug () {
    echo "$(date '+%Y-%m-%d %T') [DEBUG] $@" | tee -a $LogFile
}

## Init #####################
URLList=$ScriptPath/ab2p.source
if [ ! -e $URLList ]; then
    LogErr "missing conf file: $URLList"
fi

PrivoxyData=/var/data/ab2p
if [ ! -e $PrivoxyFilterDir ]; then
    mkdir $PrivoxyFilterDir
fi

PrivoxyFilterDir=/var/data/ab2p/privoxy
if [ ! -e $PrivoxyFilterDir ]; then
    mkdir $PrivoxyFilterDir
fi

AdblockFilterDir=/var/data/ab2p/adblock
if [ ! -e $AdblockFilterDir ]; then
    mkdir $AdblockFilterDir
fi

BackupDir=/var/data/ab2p/backup
if [ ! -e $BackupDir ]; then
    mkdir $BackupDir
fi

## Main ####################
LogInfo "Start"

LogInfo "Update Adblock Filters"
for TargetUrl in $(grep -v \# $URLList)
do
    LogInfo "TargetUrl: $TargetUrl"
    wget -N -nv $TargetUrl -P $AdblockFilterDir 2>> $LogFile
    if [ $? -ne 0 ]; then
        LogWarn "probqrem occurred: $TargetUrl"
    fi
done

LogInfo "Convert To Privoxy Filters"
adblock2privoxy -p $PrivoxyFilterDir $AdblockFilterDir/* &>> $LogFile
cp $PrivoxyFilterDir/* /etc/privoxy/ab2p

LogInfo "Archive Files"
tar cf $BackupDir/PrivoxyFilter_$(date '+%Y-%m-%d').tar.gz $URLList $AdblockFilterDir $PrivoxyFilterDir

LogInfo "End"
exit 0

処理に必要なディレクトリ等も作成しておく.

$ sudo mkdir -p /var/data/ab2p/{privoxy,adblock,backup} /var/log/script/

定期的にフィルタを更新するように root の crontab に以下設定した. 毎月1日にフィルタを更新する.

0 0 1 * * /opt/script/ab2p.sh

その他の設定

ファイアウォール

$ sudo firewall-cmd --zone=public --add-service=squid --permanent 
$ sudo firewall-cmd --zone=public --add-service=privoxy --permanent 

サービス自動起動設定と起動

$ sudo systemctl enable squid.service privoxy.service
$ sudo systemctl start squid.service
$ sudo systemctl start privoxy.service

他なにかしたっけか...

おわりに

RaspberryPi だと adblock2privoxy がインストールできないため,フィルタ変換処理を別サーバで実行する必要があった.
今回は CentOS で作ったので自動的にフィルタを更新できるようになった.
プロキシさえ設定してしまえばLAN内のPCだろうがスマホだろうが広告を削除してくれて便利.

余談
構築当初 /etc/privoxy/ab2p をシンボリックリンクで作成して privoxy がエラーを吐くという落とし穴にハマった.
privoxyシンボリックリンクを処理できないらしい.

余談2
そろそろ CentOS8 を触りたい.

余談3 これで全ての広告に対応出来る訳ではないし,広告掲載自体を否定している訳でもない.