Create TOC

레이블이 Raspberry Pi인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Raspberry Pi인 게시물을 표시합니다. 모든 게시물 표시

2021년 10월 25일

img 파일 mount

raspberry pi OS의 /boot폴더가 손상될 경우 부팅이 안된다. 이때 새로 설치하지 않고 raspberry pi OS에서 /boot만 추출해서 복구해본다.

mount를 위해서 offset 값을 구해야 한다. 우선 fdisk 명령으로 시작 sector (Start)와 크기(Secror size)를 구한다.

$ sudo fdisk -l 2021-05-07-raspios-buster-armhf-lite.img
Disk 2021-05-07-raspios-buster-armhf-lite.img: 1.75 GiB, 1874853888 bytes, 3661824 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x9730496b

Device                                    Boot  Start     End Sectors  Size Id Type
2021-05-07-raspios-buster-armhf-lite.img1        8192  532479  524288  256M  c W95 FAT32 (LBA)
2021-05-07-raspios-buster-armhf-lite.img2      532480 3661823 3129344  1.5G 83 Linux

8192에 512를 곱한 수를 offset으로 사용한다.

$ sudo mount -o loop,offset=$((8192*512)) 2021-05-07-raspios-buster-armhf-lite.img /mmt/test

2020년 8월 29일

Raspberry Pi4/몇 가지 팁

wifi/bluetooth 끄기

/boot/config.txt에 dtoverlay=disable-wifi, dtoverlay=disable-bt를 추가한다.

[all]
dtoverlay=disable-wifi
dtoverlay=disable-bt

IPv6 끄기

sysctl 설정을 추가한다.

$ sudo vi /etc/sysctl.d/local.conf
# Disable IPv6
net.ipv6.conf.all.disable_ipv6 = 1

pigpiod 오류

IPv6를 끄면 pigpiod.service가 동작하지 않는다.V73에서는 수정되었다고 한다. /lib/systemd/system/pigpiod.service에서 pigpiod 에 -n 127.0.0.1 옵션을 추가해준다.

[Service]
ExecStart=/usr/bin/pigpiod -l -n 127.0.0.1

dhcp 서비스가 오류나면서 ip를 잃어버릴 때

docker를 사용하는 경우 아래와 같이 docker에서 사용하는 interface를 제외시킨다.

$ sudo vi /etc/dhcpcd.conf
denyinterfaces veth*

오류 발생시 고정 ip를 사용하도록 설정을 추가한다.

$ sudo vi /etc/dhcpcd.conf

# It is possible to fall back to a static IP if DHCP fails:
# define static profile
profile static_eth0
static ip_address=192.168.0.x/24
static routers=192.168.0.100
static domain_name_servers=1.1.1.1

# fallback to static profile on eth0
interface eth0
fallback static_eth0

2020년 7월 20일

Raspbian/Watchdog 설정

Raspberry pi에는 hardware watchdog timer가 있다. 이를 활용하면 문제가 발생했을 때 자동으로 재부팅시킬 수 있다.

watchdog timer가 있는지 확인안다.

$ dmesg | grep -i watchdog
[    0.399099] bcm2835-wdt bcm2835-wdt: Broadcom BCM2835 watchdog timer

/etc/systemd/system.conf 파일에서 RuntimeWatchdogSec 값과 ShutdownWatchdogSec 값을 바꾼다.

RuntimeWatchdogSec=15
RebootWatchdogSec=5min

재부팅 후 watchdog 설정이 적용된 것을 확인한다.


$ dmesg | grep -i watchdog
[    0.399099] bcm2835-wdt bcm2835-wdt: Broadcom BCM2835 watchdog timer
[    1.364292] systemd[1]: Hardware watchdog 'Broadcom BCM2835 Watchdog timer', version 0
[    1.364350] systemd[1]: Set hardware watchdog to 15s.

2020년 1월 3일

Raspbian/docker + GreenTunnel

raspbian에서 GreenTunnel을 docker로 올리는 방법을 기술한다.

docker image 만들기

GreenTunnel 소스를 받는다

$ git clone https://github.com/SadeghHayeri/GreenTunnel GreenTunnel

GreenTunnel/Dockerfile 파일에서 FROM 부분을 아래와 같이 수정한다.

FROM node:lts-buster-slim

이미지를 빌드한다.

$ cd GreenTunnel
$ sudo docker build --tag green-tunnel ./

이미지가 생성되었는지 확인한다.

$ sudo docker images
REPOSITORY                    TAG                 IMAGE ID            CREATED             SIZE
green-tunnel                  latest              e0f67216c1d5        19 hours ago        158MB
node                          lts-buster-slim     b490682c0125        5 days ago          134MB

docker-compose.yml

version: "3"

services:
    green-tunnel:
        container_name: green-tunnel
        image: green-tunnel
        ports:
            - "8000:8000/tcp"
        restart: unless-stopped

docker-compose 명령으로 container를 만든다.

$ sudo docker-compose up -d

테스트

GreenTunnel을 실행시킨 raspberry pi의 ip와 port 8000 으로Firefox 등의 웹 브라우저의 proxy 설정에서 https proxy를 설정한다.

GreenTunnel 로그는 아래 명령으로 확인할 수 있다.

$ sudo docker logs -f green-tunnel

proxy.pac

이제 원하는 사이트에 접속할 때만 GreenTunnel 을 사용하도록 자동 프록시 설정 파일(proxy.pac)을 만든다.

예제는 https://abc*.net, https://def.net, 접속에서만 GreenTunnel을 사용하도록 설정했다.

function FindProxyForURL(url, host) {
    url = url.toLowerCase();
    host = host.toLowerCase();

    isHttp=(url.substring(0, 5) == "http:");

    if (isHttp) {
        return "DIRECT";
    }

    if (0
        || isPlainHostName(host)
        || shExpMatch(host, "*.local")
        || isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0")
        || isInNet(dnsResolve(host), "172.16.0.0",  "255.240.0.0")
        || isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0")
        || isInNet(dnsResolve(host), "127.0.0.0", "255.255.255.0")
        ) {
        return "DIRECT";
    }

    if (0
        || shExpMatch(url, "https://abc*.net/*")
        || shExpMatch(url, "https://def.net/*")
        ) {
        return "PROXY GreenTunnel주소:8000";
    }
    return "DIRECT";
}

proxy.pac을 http 로 접속 가능한 위치에 올리고 원하는 브라우저나 시스템 설정에서 http://어딘가/proxy.pac 형식으로 자동 프록시를 등록하면 된다.

2019년 12월 26일

Raspbian/docker + mariadb

Raspbian에서 mariadb를 docker로 올리는 방법을 기술한다.

docker-compose.yml

/docker/mariadb/config에 설정을 저장하는 것으로 설정 파일을 구성한다. 이 경로는 원하는 곳으로 바꾸면 된다.

root의 초기 비밀 번호는 ROOT_ACCESS_PASSWORD 로 설정했다.

db 관리를 위해 adminer도 같이 설치한다. mariadb가 구동되는 ip를 x.x.x.x 라고 가정했다.

version: "3"

services:
    mariadb:
        container_name: mariadb
        image: linuxserver/mariadb
        ports:
            - '3306:3306/tcp'
        environment:
            - TZ=Asia/Seoul
            - PUID=1001
            - PGID=1001
            - MYSQL_ROOT_PASSWORD=ROOT_ACCESS_PASSWORD
        volumes:
            - '//docker/mariadb/config/:/config/'
        restart: unless-stopped

    adminer:
        container_name: adminer
        image: adminer
        ports:
            - '8080:8080/tcp'
        environment:
            - TZ=Asia/Seoul
            - ADMINER_DEFAULT_SERVER=x.x.x.x
            - ADMINER_PLUGINS=tables-filter tinymce
        restart: unless-stopped

실행

docker-compose 명령으로 실행한다.

$ sudo docker-compose up -d

실행이 잘 되면 바로 root의 비밀번호를 변경한다.

$ sudo docker exec -it mariadb mysqladmin -u root -p password '새비밀번호'
Enter password:

이제 http://x.x.x.x:8080 으로 접속하면 웹으로 db를 관리할 수 있다.

2019년 12월 16일

Raspbian/사용하던 서비스를 docker로 이전

기존에 사용하던 서비스를 docker로 옮기는 과정을 기술한다.

docker로 옮길 서비스는 아래와 같다.

  • certbot
  • pihole + dnscrypt
  • tvheadend
  • nginx
  • homebridge

docker 환경 구성

docker 설치

get-docker.sh 를 이용해 설치한다.

$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

docker 그룹에 계정을 추가하면 sudo 없이 docker를 실행할 수 있다.

$ usermod -aG docker pi
$ sudo mkdir /docker
$ chown pi /docker

docker-compose 설치

$ sudo apt-get install docker-compose

certbot

설정 옮김

$ mkdir /docker/certbot
$ sudo cp -R /etc/letsencrypt /docker/certbot/config

docker-compose.yml

아래와 같은 /docker/certbot/docker-compose.yml 파일을 만든다.

version: "3"

services:
    certbot:
        container_name: certbot
        image: tobi312/rpi-certbot
        ports:
            - "80:80/tcp"
            - "443:443/tcp"
        entrypoint: certbot renew
        volumes:
            - '/docker/certbot/config/letsencrypt:/etc/letsencrypt'

테스트

$ cd /docker/certbot
$ docker-compose up

문제 없다면 /docker/certbot/docker-compose.yml 파일에서 entrypoint 를 아래와 같이 변경한다.

entrypoint: certbot -q renew

cron

2일 간격으로 인증서 갱신을 위해 certbot을 실행하도록 /etc/cron.d/certbot 파일을 만든다.

0 0 */2 * * root test -x /usr/bin/docker-compose && perl -e 'sleep int(rand(43200))' && docker-compose -f /docker/certbot/docker-compose.yml up

pihole

dnscrypt-proxy-2 대신 cloudflared 를 사용하게 변경했다.

설정 옮김

$ mkdir -p /docker/pihole/
$ sudo cp -R /etc/dnsmasq.d /docker/pihole/config
$ sudo cp -R /etc/pihole /docker/pihole/config

설정 수정

/docker/pihole/config/dnsmasq.d/01-pihole.conf 파일에서 server 를 아래와 같이 수정한다.

server=10.0.0.2#54

/docker/pihole/config/pihole/setupVars.conf 파일에서 PIHOLE_DNS 를 아래와 같이 수정한다.

PIHOLE_DNS_1='10.0.0.2#54'PIHOLE_DNS_2=''

docker-compose.yml

아래와 같이 /docker/pihole/docker-compose.yml 파일을 만든다.

version: "3"

services:
    cloudflared:
        image: visibilityspots/cloudflared
        environment:
            - TZ=Asia/Seoul
        networks:
            pihole_net:
                ipv4_address: 10.0.0.2
        restart: unless-stopped

    app:
        image: pihole/pihole:latest
        ports:
            - '53:53/tcp'
            - '53:53/udp'
            - '8888:80/udp'
        environment:
            - TZ=Asia/Seoul
            - DNS1=10.0.0.2#54
            - DNS2=
            - DNSSEC=true
            - IPv6=false
            - PUID=1000
            - PGID=1000

        volumes:
            - '/docker/pihole/config/pihole/:/etc/pihole/'
            - '/docker/pihole/config/dnsmasq.d/:/etc/dnsmasq.d/'
        networks:
            pihole_net:
                ipv4_address: 10.0.0.3
        dns:
            - 127.0.0.1
            - 1.1.1.1
        restart: unless-stopped

networks:
    pihole_net:
        driver: bridge
        ipam:
            config:
                - subnet: 10.0.0.0/29

테스트

아래와 같이 기존 서비스를 중지하고 docker로 pihole 을 실행한다.

$ sudo systemctl stop dnscrypt-proxy.service
$ sudo pihole disable
$ cd /docker/pihole
$ docker-compose up -d

nslookup 으로 dns query가 잘 되는지 확인한다. 문제가 있다면 docker-compose -f /docker/pihole/docker-compose.yml logs app 명령으로 로그를 확인해 본다.

문제가 없는 것이 확인되면 설치되어 있던 dnscrypt-proxy-2와 pihole는 삭제한다.

기타

pihole-FTL 사용법

pihole-FTL은 아래와 같이 container에서 명령을 실행해서 사용할 수 있다.

$ docker-compose -f /docker/pihole/docker-compose.yml exec app bash -c 'echo ">stats" | nc -w 1 127.0.0.1 4711'

lighttpd 중지

안쓰는 웹서버는 아래 명령으로 중지해놓는다.

$ docker-compose -f /docker/pihole/docker-compose.yml exec app service lighttpd stop

tvheadend

설정 옮김

$ mkdir /docker/tvheadend
$ mkdir /docker/tvheadend/rec
$ sudo -s
# cd /home/hts/.hts
# tar cvfj /docker/tvheadend/tvh.tar.bz2 tvheadend
# exit
$ cd /docker/tvheadend
$ sudo tar xvfj tvh.tar.bz2
$ sudo mv tvheadend config
$ sudo rm tvh.tar.bz2

docker-compose.yml

아래와 같이 /docker/tvheaded/docker-compose.yml 파일을 만든다.

version: "3"

services:
    app:
        image: linuxserver/tvheadend
        ports:
            - "9981:9981/tcp"
            - "9982:9982/tcp"
        environment:
            - TZ=Asia/Seoul
            - PUID=1000
            - PGID=1000
        devices:
            - "/dev/dvb:/dev/dvb"
        volumes:
            - '/docker/tvheadend/config:/config'
            - '/docker/tvheadend/rec:/recordings'
        restart: unless-stopped

테스트

$ cd /docker/tvheadend
$ docker-compose up -d

문제

encoding 이슈

nginx

설정 옮김

기존 설치된 nginx 설정 구조와 docker image의 구조가 달라서 우선 docker image를 설치하고 설정을 수정한다.

docker-compose.yml

아래와 같이 /docker/nginx/docker-compose.yml 파일을 만든다.

version: "3"

services:
    app:
        image: linuxserver/nginx
        network_mode: host
        environment:
            - TZ=Asia/Seoul
            - PUID=1000
            - PGID=1000
        volumes:
            - '/docker/certbot/config/letsencrypt:/etc/letsencrypt'
            - '/docker/nginx/config:/config'
            - '/media/www:/mediw/www'
        restart: unless-stopped

설정 수정

우선 container를 실행한다.

$ cd /docker/nginx
$ docker-compose up -d

ssl

/etc/nginx/ssl 폴더가 있다면 /docker/nginx/config/nginx/ssl 로 복사

nginx

linuxserver/nginx 이미지를 그대로 사용하면 nginx에 많은 모듈이 동작하게 된다.

원하는 모듈만 동작하게 하기 위해 /docker/nginx/config/nginx/nginx.conf 파일에서 기존 /etc/nginx/modules/*.conf 대신 /config/nginx/modules/*.conf 를 사용하도록 수정한다.

# include /etc/nginx/modules/*.conf;
include /config/nginx/modules/*.conf;

/docker/nginx/config/nginx/modules 폴더를 만들고 원하는 모듈의 *.conf만 복사한다.

사용가능한 모듈의 conf는 아래 명령으로 확인할 수 있다.

$ docker-compose -f ~/docker/nginx/docker-compose.yml exec app ls /etc/nginx/modules

복사는 아래와 같이 한다.

$ docker-compose -f ~/docker/nginx/docker-compose.yml exec app cp /etc/nginx/modules/http_echo.conf /config/nginx/modules

site-confs

/docker/nginx/config/nginx/site-confs/default 파일 내용을 비우고 /etc/nginx/site-enabled 파일을 가져온다.

가져온 site 설정에서 아래 내용을 수정한다.

  1. /etc/nginx/ssl 부분을 /config/nginx/ssl 로 변경
  2. log 경로를 /config/nginx/log 로 변경
  3. auth_basic_user_file 을 사용하고 있었다면 파일 경로를 /config/nginx 아래로 변경하고 기존에 사용하던 auth_basic_user_file 을 /docker/nginx/config/nginx 의 정해둔 경로로 복사.

homebridge

설정 옮김

$ mkdir /docker/homebridge
$ cp -R ~/.homebridge /docker/homebridge/config

/docker/homebridge/config/startup.sh 파일을 만들고 설치할 package를 등록한다.

#!/bin/sh

if [ ! -f /homebridge/.install_done ]; then
    npm i miio
    npm i homebridge-websocket
    npm i homebridge-mi-fan
    npm i homebridge-mi-pm2_5
    npm i homebridge-http-temperature-humidity
    touch /homebridge/.install_done
fi;

docker-compose.yml

아래와 같이 /docker/nginx/docker-compose.yml 파일을 만든다.

version: "3"

services:
    app:
        image: oznu/homebridge:raspberry-pi
        network_mode: host
        environment:
            - TZ=Asia/Seoul
            - PUID=1000
            - PGID=1000
            - HOMEBRIDGE_INSECURE=1
            - HOMEBRIDGE_CONFig_UI=1
            - HOMEBRIDGE_CONFig_UI_PORT=18080
        volumes:
            - '/docker/homebridge/config:/homebridge'
        restart: unless-stopped

테스트

기존에 실행하던 homebridge를 중지하고 homebridge container를 실행한다.

$ cd /docker/homebridge
$ docker-compose up -d

로그를 확인해보고 web ui 접속도 해본다.

$ docker-compose -f /docker/homebridge/docker-compose.yml logs app

2019년 6월 27일

Rasbian/Stretch에서 Buster로 판올림하기

Raspbian을 Stretch에서 Buster로 판올림한다.

source list 수정

/etc/apt/sourcelist.list 파일과 /etc/apt/sourcelist.d/ 디렉토리의 모든 파일에서 stretch 를 buster 로 변경한다.

패키지 목록 갱신

아래 명령으로 패키지 목록을 갱신 한다.

$ sudo apt update

이때 GPG 오류가 발생할 수 있다.

W: GPG Error http://deb.debian.org/debian buster-backports InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7638D0442B90D010 NO_PUBKEY 04EE7237B7D453EC
E: The repository 'http://deb.debian.org/debian buster-backports InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.

우선 keyring package를 설치하고 다시 시도 해본다

$ sudo apt install debian-keyring raspbian-archive-keyring
$ sudo apt update

여전히 오류가 발생한다면 오류 메시지 중 NO_PUBKEY 뒤 문자열을 가지고 key를 찾아 등록한다.

$ gpg --keyserver pgpkeys.mit.edu --recv-key 7638D0442B90D010
$ gpg -a --export 7638D0442B90D010 | sudo apt-key add -
$ gpg --keyserver pgpkeys.mit.edu --recv-key 04EE7237B7D453EC
$ gpg -a --export 04EE7237B7D453EC | sudo apt-key add -

업그레이드

$ sudo apt upgrade
$ sudo apt dist-upgrade
$ sudo apt autoremove

버전 확인은 /etc/debianversion_ 파일 내용을 확인하면 된다.

$ cat /etc/debian_version
10.0

2019년 3월 13일

Raspbian/certbot 업그레이드

How to stop using TLS-SNI–01 with Certbot을 적용하려면 certbot 버전이 0.28 이상이어야 한다. 그러나 raspbian에 포함된 버전은 0.10 이다. 아래와 같은 방법으로 certbot을 업그레이드 한다.

우선 /etc/apt/sources.list.d/debian-stretch-backports.list 에 stretch-backports 를 추가한다.

deb http://deb.debian.org/debian stretch-backports main

업데이트 할 때 key 오류가 난다.

$ sudo apt-get update

...
W: GPG error: http://ftp.debian.org jessie-backports InRelease:
   The following signatures couldn't be verified because the public
   key is not available: NO_PUBKEY 8B48AD6246925553 NO_PUBKEY
   7638D0442B90D010

아래 명령으로 key를 가져온다.

$ sudo gpg --keyserver pgp.mit.edu --recv-keys 8B48AD6246925553 7638D0442B90D010

결과 메시지에서 가져온 key 정보를 확인한다.


gpg: key 8B48AD6246925553: 28 signatures not checked due to missing keys
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 8B48AD6246925553: public key "Debian Archive Automatic Signing Key (7.0/wheezy) <ftpmaster@debian.org>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1

가져온 키를 추가한다. 이때는 sudo 대신 root shell 에서 작업한다.

$ sudo -s
# gpg --armor --export 8B48AD6246925553 | apt-key add -

패키지 목록을 갱신하고 certbot을 업그레이드 한다.

$ sudo apt-get update
$ apt-get install certbot -t stretch-backports

2018년 5월 10일

pi-hole + DNSCrypt

DNSCrypt 설치 및 설청

아래와 같이 DNSCrypt를 설치한다.

$ wget https://github.com/jedisct1/dnscrypt-proxy/releases/download/2.0.11/dnscrypt-proxy-linux_arm-2.0.11.tar.gz
$ tar xvfz dnscrypt-proxy-linux_arm-2.0.11.tar.gz
$ mv linux-arm dnscrypt-proxy
$ sudo mv dnscrypt-proxy /opt

아래와 같이 예제 설정 파일을 복사한다.

$ cd /opt/dnscrypt-proxy
$ sudo cp example-dnscrypt-proxy.toml dnscrypt-proxy.toml

/opt/dnscrypt-proxy/dnscrypt-proxy.toml에서 원하는 설정을 변경하면 된다.

server_names = ['cloudflare', 'arvind-io', 'google']
listen_addresses = ['127.0.0.1:55', '[::1]:55']
require_dnssec = true

설정이 끝나면 아래 명령으로 서비스를 등록한다.

$ sudo /opt/dnscrypt-proxy/dnscrypt-proxy -service install

아래 명령으로 실행한다.

$ sudo systemctl start dnscrypt-proxy.service

pi-hole 설정

4.0 이상

4.0 부터는 DNS 서버를 dnsmasq를 사용하지 않기 때문에 pihole 설정을 직접 수정해야 한다. /etc/pihole/setupVars.conf파일에서 PIHOLE_DNS_1값을 수정한다.

PIHOLE_DNS_1=127.0.0.1#55

DNS 서버를 다시 시작한다.

$ sudo pihole restartdns

4.0 이전

/etc/dnsmasq.d/01-pihole.conf 파일에서 server=로 시작하는 줄을 아래와 같이 #을 붙여서 주석 처리 한다.

#server=1.1.1.1
#server=1.0.0.1

아래와 같은 내용으로 /etc/dnsmasq.d/02-dnscrypt.conf 파일을 만든다.

server=127.0.0.1#55

/etc/pihole/setupVars.conf 파일에서 PIHOLE_DNS로 시작하는 줄을 모두 주석 처리 한다.

그 후 dnsmasq를 재시작한다.

$ sudo systemctl restart dnsmasq.service

테스트

설정이 완료되면 DNSSEC Resolver Test 사이트에 접속해서 확인해본다.

2018년 5월 8일

pi-hole + DNS over HTTPS

Cloudflared 설치 및 설청

아래와 같이 CloudFlared를 설치한다.

$ wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
$ tar xvfz cloudflared-stable-linux-arm.tgz
$ rm cloudflared-stable-linux-arm.tgz
$ sudo mv cloudflared /usr/local/bin

아래 명령을 실행해서 실행되는지 확인한다.

$ sudo cloudfalred proxy-dns --port 54 --upstream https://1.1.1.1/.well-known/dns-query --upstream https://1.0.0.1/.well-
known/dns-query

실행되는 것을 확인했으면 Ctrl-C로 중지 시키고 아래와 같은 내용으로 /usr/local/etc/cloudflared/config.yaml 파일을 만든다.

proxy-dns: true
proxy-dns-port: 54
proxy-dns-upstream:
 - https://1.1.1.1/.well-known/dns-query
 - https://1.0.0.1/.well-known/dns-query

서비스 등록을 위해 아래와 같은 내용으로 /etc/systemd/system/dnsproxy.service 파일을 만든다.

[Unit]
Description=CloudFlare DNS over HTTPS Proxy
Wants=network-online.target
After=network.target network-online.target

[Service]
ExecStart=/usr/local/bin/cloudflared
Restart=on-abort

[Install]
WantedBy=multi-user.target

파일을 만든 후에는 아래 명령을 이용해 dnsproxy.service활성화시킨다.

$ sudo systemctl enable dnsproxy.service

아래 명령으로 실행한다.

$ sudo systemctl start dnsproxy.service

pi-hole 설정

4.0 이상

4.0 부터는 DNS 서버를 dnsmasq를 사용하지 않기 때문에 pihole 설정을 직접 수정해야 한다. /etc/pihole/setupVars.conf파일에서 PIHOLE_DNS_1값을 수정한다.

PIHOLE_DNS_1=127.0.0.1#54

DNS 서버를 다시 시작한다.

$ sudo pihole restartdns

4.0 이전

/etc/dnsmasq.d/01-pihole.conf 파일에서 server=로 시작하는 줄을 아래와 같이 #을 붙여서 주석 처리 한다.

#server=1.1.1.1
#server=1.0.0.1

아래와 같은 내용으로 /etc/dnsmasq.d/02-cloudflare.conf 파일을 만든다.

server=127.0.0.1#54

/etc/pihole/setupVars.conf 파일에서 PIHOLE_DNS로 시작하는 줄을 모두 주석 처리 한다.

그 후 dnsmasq를 재시작한다.

$ sudo systemctl restart dnsmasq.service

테스트

설정이 완료되면 DNSSEC Resolver Test 사이트에 접속해서 확인해본다.

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 주소

2017년 3월 26일

Raspbian/RealVNC 를 설정

Raspbian에 RealVNC가 제공된다. 항상 X를 사용하지는 않기 때문에 Virtual Mode를 설정하면 되지만, vncserver-virtuald.service를 제대로 사용하려면 RealVNC 계정을 만들어야 한다.항상 X를 사용한다면 vncserver-x11-serviced.service을 사용하면 된다.

계정을 만들지 않고 Virtual Mode를 사용할 수 있도록 설정한다.

RealVNC 설치

$ sudo apt-get install realvnc-vnc-server

RealVNC 서비스 중지

$ sudo systemctl disable vncserver-x11-serviced.service
$ sudo systemctl disable vncserver-virtuald.service

스크립트 작성

vncserver-virtuald.service를 사용하지 않고 직접 vncserver-virtual 를 사용할 경우 접속한 X 환경에서 logoff 등을 할 경우 VNC 연결이 끊어지면서 vncserver-virtual 도 종료된다.

10초마다 vncserver-virtual 가 동작 중인지 검사해서 실행시키는 스크립트를 작성한다.

스크립트는 /usr/local/bin/loop_vnc.sh로 저장한다.

#!/bin/bash
if [ -x /usr/bin/vncserver-virtual ]; then
 while [[ true ]]; do
  PS_COUNT=`ps aux | grep Xvnc | grep $USER | grep -v grep | wc --lines`
  if [ 0  == $PS_COUNT ]; then
   /usr/bin/vncserver-virtual :0
  fi
  sleep 10s
 done
fi

부팅 설정

/etc/rc.local에 아래 내용을 추가해서 부팅 할 때 스크립트를 자동으로 시작하게 설정한다. 이 때 로그인을 원하는 계정 권한으로 실행해야 하기 때문에 sudo를 사용한다.

if [ -x /usr/local/bin/loop_vnc.sh ]; then
 sudo -H -u pi /usr/local/bin/loop_vnc.sh &
fi

2016년 12월 19일

Raspbian/L2TP 서버 설정

iOS VPN 정책이 바뀌면서 ipTime의 VPN 기능을 사용할 수 없게 되었다. iOS에서 VPN을 사용할 수 있도록 Raspberry Pi에 L2TP 서버 설정을 한다.

패키지 설치

$ sudo apt-get install openswan xl2tpd ppp lsof rng-tools

네트워크 설정

포트 포워딩

공유기에서 UDP 500, 4500 포트를 Raspberry PI로 포트포워딩 한다.

Raspbian 설정

우선 아래 명령들을 실행한다.

$ sudo -s
# iptables --table nat --append POSTROUTING --jump MASQUERADE
# echo "net.ipv4.ip_forward = 1" |  tee -a /etc/sysctl.conf
# echo "net.ipv4.conf.all.accept_redirects = 0" |  tee -a /etc/sysctl.conf
# echo "net.ipv4.conf.all.send_redirects = 0" |  tee -a /etc/sysctl.conf
# for vpn in /proc/sys/net/ipv4/conf/*; do echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects; done
# exit

설정이 잘 되어있는지 확인한다.

$ sudo sysctl -p

부팅시에도 설정이 동작하도록 /etc/rc.local 파일에 아래 내용을 추가한다.

for vpn in /proc/sys/net/ipv4/conf/*; do echo 0 > $vpn/accept_redirects; echo 0 > $vpn/send_redirects; done
iptables --table nat --append POSTROUTING --jump MASQUERADE

L2TP 설정

openswan 설정

예제 설정을 복사한다.

$ sudo cp /etc/ipsec.d/examples/l2tp-psk.conf  /etc/ipsec.d/l2tp-psk.conf

/etc/ipsec.conf파일을 열어서 맨 마지막에 아래 줄을 추가한다.

include /etc/ipsec.d/l2tp-psk.conf

그리고 protostack 값을 찾아서 아래와 같이 바꾼다.

protostack=netkey

/etc/ipsec.d/l2tp-psk.conf 파일을 열어서 아래 값들을 바꾼다.

conn L2TP-PSK-noNAT
 dpddelay=30
 dpdtimeout=120
 left=
 leftprotoport=17/%any
 forceencaps=yes

conn passthrough-for-non-l2tp
 left=
 leftnexthop=<공유기 내부 IP 주소>

/var/lib/openswan/ipsec.secrets.inc 파일을 편집에서 서버 접속시 사용할 비밀문자열을 지정한다.

192.168.1.112  %any:   PSK "복잡한문자열"

설정에 문제가 없는지 확한다.


$ sudo ipsec verify

xl2tpd 설정

/etc/xl2tpd/xl2tpd.conf파일을 열어 아래 값들을 바꾼다.

[global]
ipsec saref = yes

[lns default]
ip range = <할당하고 싶은 ip 대역. 192.168.0.201-192.168.0.250>
length bit = yes
require chap = yes
refuse pap = yes
name = <적당한이름. MyVPN>
pppoptfile = /etc/ppp/options.l2tpd.lns

아래와 같은 내용으로 /etc/ppp/options.l2tpd.lns파일을 만든다.

ipcp-accept-local
ipcp-accept-remote
require-mschap-v2
ms-dns 8.8.8.8
ms-dns 8.8.4.4
asyncmap 0
auth
crtscts
lock
idle 1800
mtu 1200
mru 1200
modem
debug
name l2tpd
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4
nodefaultroute
connect-delay 5000

/etc/ppp/chap-secrets 파일을 열어서 접속할 때 사용할 id, 비밀번호를 설정한다.

# Secrets for authentication using CHAP
# client    server  secret          IP addresses

아이디 l2tpd   비밀번호   *

서비스 설정

$ sudo update-rc.d -f ipsec remove
$ sudo update-rc.d ipsec defaults

서비스 재시작

$ sudo /etc/init.d/xl2tpd restart
$ sudo /etc/init.d/ipsec restart

2016년 11월 28일

Raspbian/Let's encrypt 설정

Raspbian에서 Let's encrypt 인증서를 설치하는 방법을 기술한다.

letsencrypt 설치

$ sudo -s
# gpg --keyserver pgpkeys.mit.edu --recv-key  8B48AD6246925553      
# gpg -a --export 8B48AD6246925553 | apt-key add -
# gpg --keyserver pgpkeys.mit.edu --recv-key 7638D0442B90D010      
# gpg -a --export 7638D0442B90D010 | apt-key add -
# echo "deb http://httpredir.debian.org/debian jessie-backports main contrib non-free" > /etc/apt/sources.list.d/debian-jessie-backports.list
# exit
$ sudo apt-get update
$ sudo apt-get install letsencrypt -t jessie-backports

인증서 생성

인증서 생성 전에 외부에서 433 포트로 접속 가능하도록 설정해야 한다.

$ sudo letsencrypt certonly --agree-tos --email 이메일주소 --standalone --domains 서버명

생성에 성공하면 /etc/letsencrypt/archive/서버명 디렉토리에 인증서가 저장되고 /etc/letsencrypt/live 디렉토리에 링크가 생성된다.

인증서 갱신

apt-get으로 letsencrypt을 설치한 경우에는 /etc/cron.d/certbot이 등록되기 때문에 갱신에 대해 따로 설정하지 않아도 된다.

현재 환경에서 인증서 갱신이 되는지는 아래 명령으로 테스트해보면 된다.

$ sudo cert-bot renew --dry-run

2016년 10월 11일

Raspbian/ffmpeg 빌드

raspiberry pi 3에서 사용할 ffmpeg를 빌드하는 방법을 설명한다.

빌드 환경 구성

패키지 설치

$ apt-get install git cmake build-essential libomxil-bellagio-dev libx264-dev libass-dev libfreetype6-dev libmp3lame-dev

MMAL 설치

$ git clone https://github.com/raspberrypi/userland.git
$ cd userland
$ ./buildme

빌드된 파일은 /opt/vc에 설치된다.

빌드

$ sudo apt-get install  libx264-dev libass-dev libfreetype6-dev libmp3lame-dev
$ git clone git://source.ffmpeg.org/ffmpeg.git
$ cd ffmpeg
$ ./configure --enable-libfreetype --enable-gpl --enable-nonfree --enable-libx264 --enable-libfaac --enable-libmp3lame --bindir=/usr/local/bin --enable-static --enable-omx-rpi --enable-mmal
$ make -j4
$ sudo make install

빌드가 완료되면 아래와 같이 실행해서 codec을 확인해본다.

$ ffmpeg -codecs | grep "\(mmal\|omx\)"
ffmpeg version N-81883-gbeb877b Copyright (c) 2000-2016 the FFmpeg developers
  built with gcc 4.9.2 (Raspbian 4.9.2-10)
  configuration: --enable-libfreetype --enable-gpl --enable-nonfree --enable-libx264 --enable-libass --enable-libmp3lame --bindir=/usr/local/bin --enable-static --enable-omx-rpi --enable-mmal
  libavutil      55. 32.100 / 55. 32.100
  libavcodec     57. 60.101 / 57. 60.101
  libavformat    57. 51.102 / 57. 51.102
  libavdevice    57.  0.102 / 57.  0.102
  libavfilter     6. 63.100 /  6. 63.100
  libswscale      4.  1.100 /  4.  1.100
  libswresample   2.  2.100 /  2.  2.100
  libpostproc    54.  0.100 / 54.  0.100
 DEV.LS h264                 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (decoders: h264 h264_mmal ) (encoders: libx264 libx264rgb h264_omx )
 DEV.L. mpeg2video           MPEG-2 video (decoders: mpeg2video mpegvideo mpeg2_mmal )
 DEV.L. mpeg4                MPEG-4 part 2 (decoders: mpeg4 mpeg4_mmal )
 D.V.L. vc1                  SMPTE VC-1 (decoders: vc1 vc1_mmal )

Raspbian/Tvheadend 빌드

tvheadend에 h264_omx 코덱을 사용할 수 있게 빌드하는 방법을 기술한다.

빌드 환경 구성

$ apt-get install git cmake build-essential debhelper pkg-config fakeroot libavahi-client-dev libssl-dev libcurl4-gnutls-dev liburiparser-dev  libogg-dev libtheora-dev libvorbis-dev

빌드

$ git clone https://github.com/tvheadend/tvheadend.git
$ cd tvheadend

소스를 받고 빌드 전 아래와 같이 Makefile.ffmpeg 파일을 수정한다.

diff --git a/Makefile.ffmpeg b/Makefile.ffmpeg
index e07ef2d..ff99604 100644
--- a/Makefile.ffmpeg
+++ b/Makefile.ffmpeg
@@ -573,6 +573,9 @@ $(LIB_ROOT)/$(FFMPEG)/.tvh_build: \
                --enable-gpl \
                --extra-cflags="$(ECFLAGS)" \
                --extra-libs="$(ELIBS)" \
+               --enable-omx-rpi --enable-mmal \
+               --enable-decoder="h264_mmal" \
+               --enable-encoder="h264_omx" \
                --pkg-config="$(ROOTDIR)/support/pkg-config.ffmpeg" \
                $(foreach component,$(COMPONENTS),--enable-$(component)) \
                $(foreach extlib,$(EXTLIBS),--enable-$(extlib)) \

h264_omx가 profile을 지원하지 않기 때문에 transcoding.c파일도 수정해야 한다.

diff --git a/src/plumbing/transcoding.c b/src/plumbing/transcoding.c
index 630bb62..ffb9657 100644
--- a/src/plumbing/transcoding.c
+++ b/src/plumbing/transcoding.c
@@ -1347,8 +1347,11 @@ transcoder_stream_video(transcoder_t *t, transcoder_stream_t *ts, th_pkt_t *pkt)
       av_dict_set(&opts, "preset",  t->t_props.tp_vcodec_preset, 0);
       tvhinfo(LS_TRANSCODE, "%04X: Using preset %s", shortid(t), t->t_props.tp_vcodec_preset);

-      // All modern devices should support "high" profile
-      av_dict_set(&opts, "profile", "high", 0);
+      if (0 != strcmp(ocodec->name, "h264_omx"))
+         {
+        // All modern devices should support "high" profile
+        av_dict_set(&opts, "profile", "high", 0);
+      }

       if (t->t_props.tp_vbitrate < 64) {
         // encode with specified quality and optimize for low latency

Makefile.ffmpeg, transcoding.c 파일 수정이 끝나면 아래와 같은 방법으로 빌드한다.

$ AUTOBUILD_CONFIGURE_EXTRA=--enable-ffmpeg_static\ --disable-libx264_static\ --disable-libx265\ --disable-libvpx\ --disable-libtheora_static\ --disable-libvorbis_static\ --disable-bintray_cache ./Autobuild.sh

빌드가 완료되면 아래와 같이 패키지를 설치한다.

$ cd ..
$ sudo dpkg -i tvheadend_4.1-2261~ga9bc3bc-dirty_armhf.deb

2016년 7월 11일

raspberrypi-ui-mods 설치 후 pkexec 문제

raspberrypi-ui-mods 설치 후 pkexec에서 추가한 계정이 표시되지 않는다. sudo 관련 정책파일을 추가해서 발생하는 문제다. 아래처럼 정책 파일을 추가해주면 된다.
$ cd /etc/polkit-1/localauthority.conf.d
$ sudo cp 51-desktop-sudo.con 61-desktop-policy-fix.conf

2016년 6월 22일

Raspbian/autofs 설정

설치

$ sudo apt-get install autofs
$ sudo mkdir /etc/auto.master.d

설정

설정이 끝나면 autofs를 다시 시작해야 한다.

디버깅

설정을 수정하면서 테스트하고 싶을 때는 아래와 같이 디버깅 모드를 사용한다.

$ sudo systemctl stop autofs
$ sudo automount -f -d

usb storage

/media/sda1으로 mount 하도록 설정한다. 아래 설정은 미디어가 vfat으로 포맷된 것을 가정하고 작성되었다.

  1. /etc/auto.master.d/media.autofs파일을 만든다

    /media  /etc/auto.master.d/media --timeout 60
    
  2. /etc/auto.master.d/media파일을 만든다.

    sda1 -fstype=auto,async,nodev,nosuid,umask=000 :/dev/sda1
    

WebDav

/mnt/net/davfs/box으로 mount 하도록 설정한다.

  1. davfs2 패키지를 설치한다.

    $ sudo apt-get install davfs2
    
  2. /etc/davfs2/secrets에 접속할 webdav 정보를 추가한다.

  3. /etc/auto.master.d/davfs.autofs파일을 만든다.

    /mnt/net/davfs /etc/auto.master.d/davfs --timeout 60
    
  4. /etc/auto.master.d/davfs파일을 만든다.

    box -fstype=davfs,uid=${UID},gid=${GID},rw,noexec,user,async :https://dav.box.com/dav
    

Raspbian/DHT22 센서 사용하기

DHT22 센서는 GPIO 4에 연결했다고 가정한다.

pigpio

GPIO 에서 값을 읽으려면 root 권한이 펼요하지만 pigpio를 사용하면 사용자 계정에서도 값을 읽을 수 있다.

설치

$ sudo apt-get install pigpio python-pigpio

설정

$ sudo systemctl enable pigpiod.service

시작

$ sudo systemctl start pigpiod.service

DHT22.py

설치

pigpio 샘플에 DHT22 를 다루는 코드가 있다.

$ wget https://raw.githubusercontent.com/joan2937/pigpio/master/EXAMPLES/Python/DHT22_AM2302_SENSOR/DHT22.py

수정

DHT22.py에서 atexit 관련 코드를 삭제한다.

그리고 GPIO 4에서 값을 읽도록 코드를 수정한다.

@@ -254,7 +254,7 @@ if __name__ == "__main__":

    pi = pigpio.pi()

-   s = DHT22.sensor(pi, 22, LED=16, power=8)
+   s = DHT22.sensor(pi, 4)

    r = 0

테스트

$ python DHT22.py
1 54.0 28.5 0.20 0 0 0 0
2 54.5 28.5 0.20 0 0 0 0
3 54.6 28.5 0.20 0 0 0 0
4 54.7 28.5 0.20 0 0 0 0

2016년 3월 7일

Raspberry Pi/Tvheadend 설정

현재 소유중인 USB TV 수신 카드(Dvico FusionHDTV5 USB Gold)를 Raspberry Pi에 연결하고, Tvheadend를 설정해서 다른 PC에서 TV 방송을 볼 수 있게 설정한다.

TV 수신 카드 설정

firmware 설치

$ sudo wget http://www.linuxtv.org/download/dvb/firmware/dvb-usb-bluebird-01.fw /lib/firmware

펌웨어 설치 후 USB TV 수신 카드를 다시 연결한다.

채널 검색

dvb-apps 패키지를 설치한다.

$ sudo apt-get install dvb-apps

아래와 같이 파일을 복사한다.

$ cp /usr/share/dvb/dvb-legacy/atsc/us-Cable-Standard-center-frequencies-QAM256 ~/kr-Cable-Standard-center-frequencies-8VSB

편집기로 kr-Cable-Standard-center-frequencies-8VSB파일을 열어서 QAM256을 8VSB로 변경한다.

변경이 끝나면 아래와 같은 방법으로 채널을 검색한다.

$ scan /usr/share/dvb/dvb-legacy/atsc/us-ATSC-center-frequencies-8VSB >> ~/channels.conf
$ scan ~/kr-Cable-Standard-center-frequencies-8VSB >> ~/channels.conf

검색 후 ~/channel.conf을 열어보면 아래와 비슷하게 채널 정보가 들어와 있다.

MBC:123012500:8VSB:17:20:1
:129012500:8VSB:33:36:2
:135012500:8VSB:17:20:1

"채널이름:주파수:나머지 정보" 형식을 가지고 있는데 이 중 주파수를 나중에 Tvheadend 설정시 사용한다.

Tvheadend 설정

저장소 추가

저장소에 대한 자세한 설명은 Tvheadend 사이트를 참고한다.

/etc/apt/sources.list.d 디렉토리에 아래와 같은 내용으로 tvheadend.list파일을 생성한다.
deb http://dl.bintray.com/tvheadend/deb jessie release

설정이 끝나면 package 정보를 업데이트 한다.

$ sudo apt-get update

설치

$ sudo apt-get install tvheadend

패키지를 설치할 때 관리자 id와 비밀번호를 입력해야 하는데, 원하는 값을 입력하면 된다. 나중에 다시 바꾸길 원하면 아래와 같은 명령을 입력하면 된다.

$ sudo dpkg-reconfigure tvheadend

설정

http://127.0.0.1:9981 로 접속해서 관리자 id와 비밀번호를 입력하면 관리 페이지를 볼 수 있다. 페이지 접속 후 Configuration 탭을 선택해서 필요한 설정을 해야 한다.

계정 설정

관리자 외에 TV를 시청할 계정을 추가한다.

iOS 기기에서 시청하기 위해서는

  • Web Interface
  • Streaming
  • Advanced Streaming
설정을 check 해주고 Streaming Profile을 matroska로 설정해줘야 한다.

그리고 kodi를 위해서 HTSP Streaming 설정도 check 해준다.

TV adapters 설정

TV adapters 설정에 들어가서 LG Electronics LGDT3303 VSB/QAM Frontend: ATSC #0을 선택하고 Enabled을 check 해준다.

Networks 설정

Networks 설정에 들어가서 Add을 누르고 ATSC Network을 추가한다.

Muxes/Services 설정

Network 추가 후 Muxes 설정으로 자동으로 Mux가 추가되어 있고 Scan 결과가 나오는데 대부분 실패했다. 자동으로 추가된 Mux를 정리하고 위에서 검색한 주파수를 이용해 Mux를 등록한다.

등록한 Mux의 Scan 결과가 OK가 나오면 Services 탭에서 검색된 채널이 표시되는 것을 확인해야 한다. Services 에 추가된 것을 확인하면 EPG 설정을 해야 한다.

EPG 설정

https://nas.moe/archives/1010를 참고해서 설정한다.

우선 Tvheadend 설정 페이지에서 EGP Grabber 설정을 들어가 XMLTV 설정을 check 해준다.

그다음 n2xml.py 파일을 받아온다. 파일을 받아온 후 아래와 같이 /usr/local/bin에 복사한다.

$ sudo cp n2xml.py /usr/local/bin
$ sudo chmod +x /usr/local/bin/n2xml.py

파일 복사 후 하루에 한번 실행하도록 /etc/cron.daily/n2xml 파일을 만든다.

#!/bin/sh

N2XML=/usr/local/bin/n2xml.py
CHANLIST=/usr/local/etc/chanlist.json
XMLTVSOCK=/home/hts/.hts/tvheadend/epggrab/xmltv.sock

if [ -x $N2XML ]; then
        if [ ! -f $CHANLIST ]; then
                $N2XML -u 1 -e 1 --chanlist $CHANLIST > /dev/null 2>&1
        fi
        if [ -S $XMLTVSOCK ]; then
                $N2XML -a --chanlist $CHANLIST -s $XMLTVSOCK > /dev/null 2>&1
        fi
fi

파일을 만든 후 실행 속성을 부과한다.

$ sudo chmod +x /etc/cron.daily/n2xml

속성 부과 후 한번 실행해준다.

$ sudo /etc/cron.daily/n2xml

그 후에 Tvheadend 설정 페이지에서 logout 후 다시 login 한다. 그 다음 Channel 페이지에 가서 Channel을 추가하면 된다.

Tvheadend 클라이언트 설정

iOS

TvhClient앱을 설치하면 된다.

설치 후 Tvheadend 서버를 추가하면 아래와 같이 채널 목록이 표시된다.

채널을 선택하면 해당 채널에 대한 상세한 방송 정보가 표시된다.

Play을 선택하면 메뉴가 하나 뜨는데 내장된 VLC로 볼 수도 있고 외부 플레이어 (NPlayer)로 링크를 넘겨서 재생할 수도 있다.

내장 VLC로도 재생이 잘 된다.

Kodi

Windows, OS/X, Linux 에서는 Kodi를 설정해서 시청하는 것이 제일 편하다.

설정 - 애드온 - PVR 클라이언트 에서 Tvheadend HTSP Client을 설치하고 설정한다.

설정 - TV - 일반을 사용함으로 설정한다.

설정이 끝나면 첫 화면에 TV 관련 메뉴가 표시된다.

채널 목록을 보고 시청이 가능하다.

방송 정보도 한번에 볼 수 있다.