(旧)OpenWrtでWPA2-Enterprise(EAP-PEAP/MSCHAPv2)の構築

FreeRADIUSをDebianに導入するのは容易ですがOpenWrt (Chaos Calmer 15.05.1)にインストールする場合はいくつか問題があります。EAP-TLSをセットアップしてみたところ次のようなエラーがありました。

Unknown TLS version [length 0002]

調べてみるとFreeRADIUSがopensslのTLSv1.2を理解できないことが原因のようです。OpenWrtでFreeRADIUSを使うことは不可能かというとそうでもありません。以前、EAP-PEAPをセットアップしたところCA証明書なしに接続できました。つまりユーザー/パスワードだけでTLS認証なしに接続できます。実際、EAP-PEAPでセットアップするとTLSも必要になるのですが、うまく回避して接続できるようです。

今回、バッファローのwmr300にインストールしてみました。この機種は携帯用に便利ですがフラッシュメモリが8MBと制約あります。それ以外は特に問題はありません。

FreeRADIUSのセットアップに必要なパッケージ

まず、FreeRADIUSのパッケージをインストールします。

# opkg update
# opkg install freeradius3 freeradius3-common freeradius3-democerts freeradius3-mod-always freeradius3-mod-attr-filter freeradius3-mod-attr-rewrite freeradius3-mod-chap freeradius3-mod-detail freeradius3-mod-eap freeradius3-mod-eap-mschapv2 freeradius3-mod-eap-peap freeradius3-mod-eap-tls freeradius3-mod-exec freeradius3-mod-expiration freeradius3-mod-expr freeradius3-mod-files freeradius3-mod-logintime
# opkg install freeradius3-mod-mschap freeradius3-mod-passwd freeradius3-mod-preprocess freeradius3-mod-radutmp freeradius3-mod-realm freeradius3-utils freeradius3-mod-digest freeradius3-mod-unix

次にopensslコマンドを使えるようにパッケージをインストールします。またWPAエンタープライズを使用するにはwpadが必要なので入れ替えます。

# opkg install openssl-util libopenssl
# opkg remove wpad-mini
# opkg install wpad

秘密鍵と証明書のインストール

opensslの使い方は過去の記事にいくつか書きましたが、今回は検索したサイトを参考に作成してみました。

# openssl ecparam -out ecca.param -name secp384r1
# openssl req -nodes -newkey ec:ecca.param -days 3650 -x509 -sha256 -keyout ecca.key -out ecca.crt
# openssl req -nodes -newkey ec:ecca.crt -days 3650 -sha256 -keyout serverec.key -out serverec.csr

# mkdir ./demoCA/
# mkdir ./demoCA/newcerts
# touch ./demoCA/index.txt
# echo 01 > ./demoCA/serial

# openssl ca -extensions v3_ca -days 3650 -out serverec.crt -in serverec.csr -cert ecca.crt -keyfile ecca.key
# cat serverec.crt serverec.key > serverec.pem
# openssl dhparam -out dhparam.pem 2048
# mkdir /etc/freeradius2/certs
# cp ecca.crt serverec.pem dhparam.pem /etc/freeradius2/certs

秘密鍵と証明書をインストールしたら証明書のテストをしてみます。

# openssl x509 -in serverec.crt -text
# openssl verify -CAfile ecca.crt serverec.pem

Freeradiusの設定

OpwnWrtのFreeRADIUSパッケージはいくつか足りないものがあり設定で補います。

/etc/freeradius2/eap.conf

eap {
    default_eap_type = peap
    timer_expire = 60
    ignore_unknown_eap_types = no
    cisco_accounting_username_bug = no
    max_sessions = ${max_requests}
    tls {
        certdir = ${confdir}/certs
        cadir = ${confdir}/certs
        private_key_file = ${certdir}/serverec.pem
        certificate_file = ${certdir}/serverec.pem
        CA_file = ${cadir}/ecca.crt
        dh_file = ${certdir}/dhparam.pem
        CA_path = ${cadir}
        cipher_list = "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA256:ECDHE-RSA-AES256-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;"
        ecdh_curve = "secp384r1"
        cache {
            enable = no
            lifetime = 24 # hours
            max_entries = 255
        }
        verify {
            tmpdir = /tmp/radiusd
            client = "/usr/bin/openssl verify -CApath ${..CA_path} %{TLS-Client-Cert-Filename}"
        }
        ocsp {
            enable = no
            override_cert_url = yes
            url = "http://127.0.0.1/ocsp/"
       }
    }
    peap {
        default_eap_type = mschapv2
        copy_request_to_tunnel = yes
        use_tunneled_reply = yes
        virtual_server = "inner-tunnel"
    }
    mschapv2 {
        send_error = no
    }
}

/etc/freeradius2/sites/default

authorize {
    preprocess
    chap
    mschap
    suffix
    eap {
        ok = return
    }
    expiration
    logintime
}
authenticate {
     Auth-Type CHAP {
        chap
    }
    Auth-Type MS-CHAP {
        mschap
    }
    eap
}
preacct {
    preprocess
    acct_unique
    suffix
    files
}
attr_filter.accounting_response
    session {
    radutmp
}
pre-proxy {
}
post-proxy {
    eap
}

/etc/freeradius2/sites/inner-tunnel

server inner-tunnel {
    listen {
       ipaddr = 127.0.0.1
       port = 18120
       type = auth
    }
    authorize {
        chap
        mschap
        suffix
        update control {
            Proxy-To-Realm := LOCAL
        }
        eap {
            ok = return
        }
        files
        expiration
        logintime
    }
    authenticate {
        Auth-Type CHAP {
            chap
        }
        Auth-Type MS-CHAP {
            mschap
        }
        eap
    }
    session {
        radutmp
    }
    post-auth {
        Post-Auth-Type REJECT {
            attr_filter.access_reject
        }
    }
    pre-proxy {
    }
    post-proxy {
        eap
    }
}

/etc/freeradius2/radiusd.conf

listen {
    type = auth
    ipaddr = 127.0.0.1
    port = 0
    interface = lo
}

...
$INCLUDE proxy.conf
...
$INCLUDE policy.conf

/etc/freeradius2/policy.conf: policy {}の中に追加します。

 acct_unique {
    update request {
        Acct-Unique-Session-Id := "%{md5:%{User-Name},%{Acct-Session-ID},%{NAS-IP-Address},%{NAS-Identi$
    }
 }

/etc/freeradius2/modules/mschap

mschap {
    use_mppe = yes
    require_encryption = yes
    require_strong = yes
    with_ntdomain_hack = no
}

/etc/freeradius2/clients.conf

client localhost {
    secret = secret123
    ipaddr = 127.0.0.1
    shortname = localAP
    require_message_authenticator = yes
    nastype = other
}

/etc/freeradius2/users

"testuser" Cleartext-Password := "pass123"

テストを行います。

# mkdir -p /tmp/radiusd
# radiusd -X

起動が確認できたら実行スクリプトを編集します。ルータをAPとして使うためにローカルホストで使えるようにします。

/etc/init.d/radiusd

...
TMP_D=/tmp/radiusd

start() {
    [ -f $DEFAULT ] && . $DEFAULT
    mkdir -p $TMP_D
    mkdir -p $LOG_D
    mkdir -p $RUN_D
    mkdir -p $RADACCT_D
    radiusd $OPTIONS
}

OpenWrtの設定

/etc/config/wireless

config wifi-iface
    option device 'radio0'
    option mode 'ap'
    option network 'lan'
    option ssid '<YOUR_SSID>'
    option encryption 'wpa2+ccmp'
    option auth_server '127.0.0.1'
    option auth_secret 'secret123'

ネットワークを再起動してアクセスします。

この設定例でアクセスするユーザー/パスワードはtestuser/pass123です。

参考:

LibreELEC 8.2.1.2バージョン

 

s905x系のアンドロイドボックスだとAndroid、LibreELECそしてArmbianの3つの選択肢があります。私のもっているものは1GBしかメモリがないのでAndroidとArmbianは動くもののスムーズに動きません。それでLibreELECという選択になるのですが、すべてのデバイスをサポートしていないという問題があります。今回、バージョンが8.2.1.2に上がっていつかデバイスがサポートしました。そのひとつが9082xsの追加です。9082xsはTX3PROのWiFiモジュールです。dockerが使えるようになるにはカーネールのアップデートが必要ですが今後期待したいところです。

 

 

Samsung Chromebook (XE303C12)にArchLinuxをインストール

ChromebookでCroutonを使わずSDから直接Linuxを立ち上げることは出来ますが、グラフィックスまわりに問題があって今までは避けていました。しかし古いChromeOSはGoogle Playが使えないので使い勝手が悪く、前回VPNの設定をしましたが動作が怪しいこともあり、今回再度、直接Linuxを立ち上げることを試してみました。SDから立ち上げるにはデベロッパーモードにしてあるのが条件です。

デスクトップ環境はKDEは重すぎて途中固まったりするので軽量のLXQtを使いました。

オーディオはPulseaudioはデバイスを認識しなかったのでAlsaを使います。

ブラウザからの動画はFirefoxは音に問題がありましたがChromiumは問題なく動作します。

Mainline Kernelにアップデート

3.8カーネールではネットワーク周りなどいくつか問題があったのでメインカーネルにアップデートしてみました。

よい点

  • ネットワーク周りが改善した

Network ManagerとVPNのルーティングの問題が解消された。

BTテザリングが使えるようになったのでほぼx86のLinuxを入れたラップトップ同様に使える。

  • dockerやsystemd-nspawnなどのコンテナが使えうようになった

dockerが使えるようになったのでemby serverなどを入れられるようになった。

悪い点

  • サウンドカードが使えない

Pulseaudioは使えるものの、内臓のサウンドカードは使えませんがUSBオーディオは使えます。

共通の不具合

  • HDMIが使えない

MISC

sudo ufw allow in proto udp to 224.0.0.0/4
sudo ufw allow in proto udp from 224.0.0.0/4

/etc/ufw/before.rules

# allow IGMP
-A ufw-before-input -p igmp -d 224.0.0.0/4 -j ACCEPT
-A ufw-before-output -p igmp -d 224.0.0.0/4 -j ACCEPT

結論

全部の機能をチェックはしていませんがストレスなく使えるレベルに仕上がっています。ブラウザ、ターミナル、グラフィックス、サウンド、ブルートゥース、Wi-Fiの基本的な機能は実用レベルです。しばらく使ってみて問題なければ内部のフラッシュメモリにインストールすることも視野に入れても良さそうです。

リンク

ChormebookのOpenVPNを使う

Chromebookには標準でOpenVPNが使えるようになっています。実際使ってみようとしたら問題があります。設定の項目があまりにも少なく、自前で作ったシステムだと動かない可能性大です。基本的にOpenVPNの場合、サーバ側とクライアント側の設定を擦り合わせておかなくてはなりません。そこでコマンドラインから起動してみることにしました。設定は他の環境と同じです。

# openvpn --config <設定ファイル>

ところが繋がった瞬間、tun/tapデバイスが消えてエラーになり結果、接続に失敗します。/dev/net/tunデバイスはあり、またカーネルモジュールも問題ありません。そこで検索したところ、次のようにすれば接続できるようになります。

エラーの状況

read from TUN/TAP : File descriptor in bad state (code=77)

解決方法

$ sudo stop shill
$ sudo start shill BLACKLISTED_DEVICES=tun0
$ sudo openvpn --config chromebook.ovpn --dev tun0

 

追記:strongSwanを使う場合

croutonのchroot環境にxenialをインストールしてstrongSwanを動かしてみました。

ChromeOS側:

# stop shill
# start shill BLACKLISTED_DEVICES=ipsec0

Xenial(chroot)側:

kernel-libipsec.conf

   load = yes

ルーティングを変更します。

# route del default gw <IP>
# route add -host <VPN IP> gw <IP>

ipsec.conf

config setup

conn %default
 ikelifetime=60m
 keylife=20m
 rekeymargin=3m
 keyingtries=1
 keyexchange=ikev2

conn ikev2
 left=%any
 leftsourceip=%config
 leftfirewall=yes
 leftauth=pubkey
 leftcert=chrome@example.crt
 right=example.net
 rightsubnet=0.0.0.0/0
 dpdaction=clear
 dpddelay=300s
 rekey=no
 reauth=no
 fragmentation=yes
 eap_identity=%any
 auto=start

ipsec statusall

 ikev2[1]: IKEv2 SPIs: c74a3c6a9904776e_i* a788d98c516b2904_r, rekeying disabled
 ikev2[1]: IKE proposal: AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_2048
 ikev2{1}: INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: f4aaf5b4_i cd6736f1_o
 ikev2{1}: AES_CBC_128/HMAC_SHA1_96, 0 bytes_i, 0 bytes_o, rekeying disabled
 ikev2{1}: 192.168.200.2/32 === 0.0.0.0/0
 ikev2{2}: INSTALLED, TUNNEL, reqid 1, ESP in UDP SPIs: 7ed1c1a4_i c5cb9e38_o
 ikev2{2}: AES_CBC_128/HMAC_SHA1_96, 268427 bytes_i (560 pkts, 3s ago), 90620 bytes_o (574 pkts, 1s ago), rekeying disabled
 ikev2{2}: 192.168.200.2/32 === 0.0.0.0/0

Chromebookでは特定のサイトだけ開けないケースが目立ちました。一つの解決方法はプロキシ経由にする方法ですが根本的に解決するにはiptablesを使います。サーバ側の設定を追加します。

iptables -t mangle -A FORWARD -m policy --pol ipsec --dir in -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
iptables -t mangle -A FORWARD -m policy --pol ipsec --dir out -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360

/etc/sysctl.conf

net.ipv4.ip_no_pmtu_disc = 0

参考:

WordPress でSMTPを使う

WordPressのプラグインWP Mail SMTPを使うとき、テストメールがエラーになったので調べてみました。

Dec  3 23:30:12 h10-1-mail postfix/smtpd[20749]: connect from unknown[10.1.1.6] 
Dec  3 23:30:13 h10-1-mail postfix/smtpd[20749]: warning: connect to Milter service inet:localhost:8891: Connection refused 
Dec  3 23:30:13 h10-1-mail postfix/smtpd[20749]: NOQUEUE: reject: RCPT from unknown[110.1.1.6]: 504 5.5.2 <110.1.1.6>: Helo command rejected: need fully-qualified hostname;

ローカルアクセスなのでFQDNでアクセスできません。検索してみたら次の方法で認証が通りました。

permit_mynetworks,

/etc/postfix/main.cf

# Anti-SPAM rules adapted from https://wiki.debian.org/Postfix 
smtpd_recipient_restrictions = permit_sasl_authenticated, 
        permit_mynetworks, 
        reject_invalid_hostname, 
        reject_unknown_recipient_domain, 
        reject_unauth_destination, 
        reject_rbl_client sbl.spamhaus.org, 
        permit 
 
smtpd_helo_restrictions = reject_invalid_helo_hostname, 
        permit_mynetworks, 
        reject_non_fqdn_helo_hostname, 
        reject_unknown_helo_hostname 
 
#        check_client_access cidr:/etc/postfix/local.cidr, 
 
smtpd_client_restrictions = reject_rbl_client dnsbl.sorbs.net

 

 

Reference:

http://postfix.1071664.n5.nabble.com/Using-quot-reject-unknown-sender-domain-quot-with-exemptions-for-certain-sender-domains-td69054.html

Dockerの非特権モード

Dockerはrootで動かすイメージが強いのですがlxcと同じように非特権モードでも動きます。lxcがベースになってるから当たり前のことですが、調べてみてもなかなか事例が見つからなかったのでまとめてみました。

まずsubuidとsubgidを編集します。linux mintを使っているのでほかのディストリビューションはわかりませんが似たような構成になっていると思います。

# cat /etc/subuid

user1:100000:65536
 lxd:165536:65536
 root:165536:65536

# cat /etc/subgid

user1:100000:65536
 lxd:165536:65536
 root:165536:65536

Dockerの設定を追加します。(例:user1)

# cat /etc/docker/daemon.json

{
 "userns-remap": "user1"
 }

起動ファイルを編集します。

# cat /etc/init.d/docker

DOCKER_OPTS="--userns-remap=default"

Dockerを再起動します。

# systemctl restart docker

これで非特権モードが使えるようになります。

Dockerの基本コマンド集

コマンドが覚えきれないのでよく使うコマンドのチートシートを作ってみました。

Dockerのイメージサーチ

docker search IMAGE

eg) docker search debian

Dockerイメージのダウンロード

docker pull IMAGE

Dockerのイメージリスト

docker images
OR
docker image list

コンテナの起動

docker run -t -i IMAGE /bin/bash

# コンテナをデーモンモードで起動する
docker run -d -t -i IMAGE /bin/bash

# コンテナ名を指定して起動する
docker run -t -i --name NAME IMAGE /bin/bash

# ホスト名を指定して起動する
docker run -t -i  -h HOST NAME --name NAME IMAGE /bin/bash

# コンテナを終了時に破棄する指定で起動する
docker run --rm -t -i IMAGE /bin/bash

# ホストのポートを割り当てて起動する
docker run -d -p 80:80 --name NAME IMAGE

Note: HOST port:CONTAINER port

# ホスト/etcをコンテナの/root/etcにマッピングして起動する
docker run -v /etc:/root/etc -t -i IMAGE

# CPUを割り当てて起動する
docker run -c 200 -i -t IAMGE /bin/bash

# メモリを割り当てて起動する
docker run -m 512m -i -t IMAGE /bin/bash

# 自動起動
docker run -dit --restart unless-stopped redis

コンテナ操作

# コンテナにアタッチする
docker attach CONTAINER ID or CONTAINER NAME

# initでコンテナを起動している場合にアクセスする
docker exec -t -i CONTAINER ID or CONTAINER NAME bash

# コンテナをスタートする
docker start CONTAINER ID or CONTAINER NAME

# コンテナをアタッチしてスタートする
docker start -a CONTAINER ID or CONTAINER NAME

# コンテナを終了する
docker stop CONTAINER ID or CONTAINER NAME

# コンテナを強制終了する
docker kill CONTAINER ID or CONTAINER NAME

Dockerの情報

# 起動しているコンテナのリスト表示する
docker ps

# 起動していないコンテナ含めてのリスト表示する
docker ps -a

# 直前に終了したコンテナの表示する
docker ps -l -q

# コンテナのプロセスを表示する
docker top CONTAINER

# コンテナのログを表示する
docker logs -f CONTAINER

# コンテナ情報を表示する
docker inspect CONTAINER

# イメージ情報を表示する
docker inspect IMAGE

# Dockerのバージョンを表示する
docker version

# 動作中のDockerの情報を表示する
docker info

削除

# コンテナを削除する
docker rm CONTAINER ID or CONTAINER NAME

# イメージを削除する
docker rmi IMAGE

イメージ操作

# コンテナからイメージを作成する
docker commit CONTAINER ID or CONTAINER NAME NEW IMAGE

# イメージをファイルに保存する
docker save IMAGE > /tmp/IMAGE.tar

# イメージを呼びこむ
docker load < /tmp/IMAGE.tar

# dockerfileからイメージをビルドする
docker build

# キャッシュを無効にしてビルドする
docker build --no-cache=true

# コンテナからtar fileを作成する
docker export CONTAINER > filename.tar

 

ネットワーク

# ネットワークブリッジを作成する
docker network create --driver bridge --subnet 172.18.0.0/16 --gateway 172.18.0.1 --opt "com.docker.network.bridge.name"="docker1" server

# ネットワークブリッジの情報を表示する
docker network inspect docker1

# ネットワークブリッジにコンテナをアタッチする
docker network connect docker1 CONTAINER ID or CONTAINER NAME