Create TOC

2018년 2월 28일

pi-hole 설치

pi-hole은 DNS에서 원하는 주소를 차단하는 기능을 제공한다. 광고서버를 차단할 수 있지만 domain 단위기 때문에 uBlock 같이 세세하게 차단할 수는 없다.

그렇지만, DNS 단에서 차단을 하기 때문에 uBlock 같은 광고 차단 프로그램을 사용할 수 없는 환경에서도 어느 정도 광고를 차단할 수 있게 된다.

설치

pi-hole설치

아래 명령으로 간단하게 설치할 수 있다. 설치하는 기기의 IP를 고정시켜야 하는 점만 주의하면 된다.

$ curl -sSL https://install.pi-hole.net | bash

보통 전체 설치할 경우 Web으로 관리할 수 있게 되지만, console 만으로도 충분히 사용 가능하다.

DNS 서버 선택
DNS 서버 주소 등록
Web 관리 사용 안함
log 남기지 않음
방화벽 규칙 추가

서비스 활성화

설치 후 아래 명령으로 서비스를 활성화한다.

$ sudo systemctl enable pihole-FTL

테스트

$ nslookup apps.id.net 127.0.0.1
Server:  127.0.0.1
Address: 127.0.0.1#53

Name: apps.id.net
Address: 0.0.0.0

공유기 설정

공유기 설정으로 들어가 pi-hole을 설치한 기기의 ip를 primary domain 으로 등록한다.

설정

규칙 추가

차단 규칙은 /etc/pihole/adlists.list파일을 편집해서 수정할 수 있다.

YousList

/etc/pihole/adlists.list파일에 아래 내용을 추가한다.

## YousList
https://raw.githubusercontent.com/yous/YousList/master/hosts.txt

adlists.list 내용을 바로 반영하기 위해 아래 명령을 실행한다.

$ sudo pihole -g

regex 규칙

pi-hole 4.0이상부터는 정규식 규칙을 추가할 수 있다.

$ curl -sSl https://raw.githubusercontent.com/mmotti/pihole-regex/master/install.sh | sudo bash

local list

규칙 파일을 만들고 적용할 수 있다. 아래와 같은 내용을 /etc/pihole/adlists.list 에 추가하고 /usr/local/etc/pihole/mylist.txt파일에 규칙을 추가하면 된다.

## mylist
file:///usr/local/etc/pihole/mylist.txt

mylist.txt은 아래와 같은 형식으로 만들면 된다.

0.0.0.0 abc.com

규칙 편집을 쉽게 하기 위해서 mylist.txt의 owner를 변경한다(사용자 계정은 pi 라고 가정한다).

$ sudo chown pi /usr/local/etc/pihole/mylist.txt

기존 uBlock에서 사용하던 광고 차단 규칙을 이용하기 위해 간단한 python script를 만들었다.

#!/usr/bin/python
# -*- coding: utf-8

import sys
import os
import re
import requests


ip_regex = re.compile('^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$')

white_lists = [
    'chosun.com',
    'donga.com',
    'hani.co.kr',
    'joins.com',
    'joongang.joins.com',
    'khan.co.kr',
    'mediawatch.kr',
    'newscj.com',
    'ohmynews.com',
    'www.chosun.com',
    'www.donga.com',
    'www.hani.co.kr',
    'www.joins.com',
    'www.joongang.joins.com',
    'www.khan.co.kr',
    'www.mediawatch.kr',
    'www.newscj.com',
    'www.ohmynews.com',
]


def is_valid(hostname):
    """규칙에 추가할 것인지 결정한다.

hostname - 검사할 이름"""
    return True if len(hostname) > 0 and hostname.find(':') == -1 and hostname.find('/') == -1 and hostname.find('*') == -1 and ip_regex.match(hostname) is None and hostname not in white_lists else False


def adblock_rule():
    """adblock 규칙중 hostname 기반 규칙에서 hostname 만 모아서 꺼낸다."""
    urls = [
        'https://raw.githubusercontent.com/NativeHyun/HyunGuard/master/General/general.txt',  # HyunGuard
        'https://raw.githubusercontent.com/SlowMemory/List-KR/master/filter.txt',  # ListKR
        'https://raw.githubusercontent.com/gfmaster/adblock-korea-contrib/master/filter.txt',  # adblock-korea-contrib
    ]

    result = list()

    s = requests.Session()

    for url in urls:
        r = s.get(url)
        if r.status_code == 200:
            result = result + [line[2:-1] for line in r.text.split('\n') if line.startswith('||') and line.endswith('^') and is_valid(line[2:-1])]

    return result


def hostfile_rule():
    """hosts 규칙중 hostname 기반 규칙에서 hostname 만 모아서 꺼낸다."""
    urls = [
        'https://godpeople.or.kr/hosts.txt',  # godpeople
        'http://www.malwaredomainlist.com/hostslist/hosts.txt',  # malware domains
        'https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=1&mimetype=plaintext&_=210978',  # Peter Lowe's Ad and tracking server list
    ]
    result = list()
    s = requests.Session()
    for url in urls:
        r = s.get(url)
        if r.status_code == 200:
            for line in r.text.split('\r\n'):
                if len(line) == 0:
                    continue
                if line.startswith('#'):
                    continue
                try:
                    host = line.replace('  ', ' ').split(' ')[1]
                    if is_valid(host):
                        result.append(host)
                except IndexError:
                    pass

    return result


def main(filename=None):
    hosts = list(set(adblock_rule() + hostfile_rule()))  # 중복 제거
    hosts.sort()

    if filename is None:
        for host in hosts:
            print '0.0.0.0 {}'.format(host)
    else:
        with file(filename, 'wt') as f:
            for host in hosts:
                f.write('0.0.0.0 {}\n'.format(host))


if __name__ == '__main__':
    filename = sys.argv[1] if len(sys.argv) >= 2 else None
    main(filename)

스크립트를 /usr/local/bin/myrule_update.py으로 저장한 후 아래와 같이 permission을 조정한다.

$ sudo chmod +x /usr/local/bin/myrule_update.py

실행할 때는 아래와 같이 실행하면 된다.

$ /usr/local/bin/myrule_update.py /usr/local/etc/pihole/mylist.txt
$ sudo pihole -g

white list 추가

clien 문제 수정

iPhone에서 ClienKit 이나 볼라고를 이용해 clien 사용시 SSL 연결 오류가 발생할 수 있다. 아래 주소를 whitelist에 등록하면 문제가 해결된다.

$ sudo pihole -w clien.net

tmdb, tving 문제 수정

$ sudo pihole -w image.tmdb.org
$ sudo pihole -w image.tving.com

명령 모음

업데이트 명령들은 crontab에 등록되어 동작하기 때문에 따로 신경쓸 필요는 없다.

규칙 업데이트

$ sudo pihole -g

pi-hole 업데이트

$ sudo pihole -up

pi-hole 중지

$ sudo pihole disable

white list 추가

$ sudo pihole -w 주소