VyOS で unbound を利用する

VyOS というより EdgeOS なのだけれど。

自宅の環境はプロバイダのルータと自前ルータ(EdgeRouter)の二段構えなのだが、EdgeRouter の DNS のフォワード先はプロバイダのルータにしていた。 しかしプロバイダのルータの DNS がたまに応答しなくなったり不安定だったので、EdgeRouter 自身に unbound を立てることにした。

とりあえず以下を参考にして apt を使えるようにする。

EdgeMAX - Add other Debian packages to EdgeOS – Ubiquiti Networks Support and Help Center

しかる後、unbound をインストールする。

sudo apt-get update
sudo apt-get install unbound

ここでポート 53 を dnsmasq が listen しているので unbound の起動がコケる。 /etc/unbound/unbound.conf を適当に書き換えてポート番号を変えておく。

server:
   ...
   interface: 127.0.0.1
   port: 10053

そして起動する。

sudo service unbound restart

あとは、configure で dnsmasq の設定をする。 非標準ポートなので options で指定して、/etc/resolv.conf を見ないように no-resolv も入れておく。

set service dns forwarding options server=127.0.0.1#10053
set service dns forwarding options no-resolv
commit
save

/etc/dnsmasq.conf を見て設定が正しいか確認しておくと良いだろう。

unbound が働いているかどうかは、sudo unbound-control stats をしてみればわかる。

systemd-networkd では netdev だけではデバイスは UP しないらしい

LXC 用の Bridge インターフェースを systemd-networkd で管理しようとして、.netdev ファイルを以下のように作った。

[NetDev]
Name=br0
Kind=bridge

この bridge に対して physical デバイスで以下のように接続しておいた。

[Match]
Name=en*

[Network]
...
Bridge=br0

これだけだと、ip link でみてみると link が DOWN になっていて、接続が出来ない。

以下のような空の .network ファイルを bridge に対して設定してやったらめでたく UP になってくれた。

[Match]
Name=br0

SSD が壊れた。

サーバ機の OS 領域として使っていた SSD が壊れてしまった。 モノは、シリコンパワー製の 32GB MLC のドライブ。型番は SP032GBSSDE20S25 らしい。 購入したのは、2012年3月なので、3年と8ヶ月で壊れたことになる。

壊れたのに気づいたのは、ホストが勝手にシャットダウンして mackerel からアラートが上がったから。 とりあえず立ち上げてみたが、ブート途中でストップしてしまった。 しばらく放置してみたら errno 16 が出ていた。EBUSY なのは応答がないからだろう。

ホスト側のコネクタ周りとかがおかしいかもしれなかったので、SATA-USB 変換器でつなげてみたが、 rw マウントしたらやはりエラーになってしまってマウントできなかった。 幸いにも ro ではマウントできデータ化けもなかったようなので、バックアップをとって余っていた HDD に適当にコピーして復旧した。

ちょっと確認したところ、特に smart ではエラーが無いように見えた。 また、OS 領域に使っていたのでログが残っておらず調査が面倒だった。

週末に IntelSSD でも買ってこよう。今度はどのくらい持つだろうか。

VyOS でプライベート DNS コンテンツサーバを参照する

VyOS は DNS フォワーダを持っているが、標準的な設定ではフォワード先は(当然ながら)フルリゾルバを指定する。 しかし、内部用の DNS コンテンツサーバを参照するだけでフルリゾルバを立てるのが面倒くさい。 特定のドメイン、及びサブドメインだけをフォワードする方法がわかったので記述する。

VyOS の DNS フォワーダは dnsmasq で実現されている。dnsmasq は特定のドメインだけ指定した DNS サーバに飛ばす設定ができるが、 VyOS の set service dns forwarding name-server コマンドではこの指定ができない。 しかし set service dns forwarding options コマンドを使うことで dnsmasq の任意の設定が記述できる。 具体的には、以下のように記述すれば良い。

set service dns forwarding options server=/my.home/10.x.y.z

rust の lifetime

まずは 1.0 alpha リリースおめでとうございます。

リリースしてドキュメント関係が差し替わって Book (旧 guide) に lifetime について乗るようになったぽい。

C++ はリファレンスによって NULL ポインタのデリファレンスを防げるようになったが、ダングリングリファレンスは依然として起こってしまう。 rust の lifetime の概念はこれを解決するためのものらしい。

lifetime は Book にあるように、 場合によって省略可能だが、コンパイラが決定できない場合ユーザーが明示的に指定する必要がある。 具体的には、以下のような場合。

fn f<'a> (x: &'a i32, y: &i32) -> &'a i32 {
    x
}

fn main() {
    let x = 1;
    let r: &i32;
    {
        let y = 2;
        r = f(&x, &y);
    }
}

この場合、f の仮引数の x と戻り値の lifetime が同一であると 'a として lifetime parameter を明示することで、 コンパイラに教えている。 この場合だと、x をリターンしているので、コンパイラでも検出できると思うが、以下のような場合を考えると、省略ルールから外れた場合は常に指定する必要があるというのは、デザインとして納得ができる。

fn f<'a> (x: &'a i32, y: &'a i32) -> &'a i32 {
    if *x == 0 {
        x
    } else {
        y
    }
}

ちなみに、最初の例で、f(&y, &x) とすると、y はスコープアウトするのに r に参照がわたってしまうので、コンパイルエラーになる。 こんな感じで rust は安全性を担保してるようだ。

複数の Trait による Restriction

Generics の restriction に複数の trait を指定したい場合、+ を使えばいいらしい。

struct Circle {
    x: f64,
    y: f64,
    radius: f64,
}

trait HasArea {
    fn area(&self) -> f64;
}

trait HasPoint {
    fn point(&self) -> (f64, f64);
}

impl HasArea for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

impl HasPoint for Circle {
    fn point(&self) -> (f64, f64) {
        (self.x, self.y)
    }
}

fn print_area_and_point<T: HasArea+HasPoint>(c: T) {
    println!("area is {}, {}", c.area(), c.point());
}

fn main() {
    let c = Circle{x: 0.0, y:0.0, radius: 1.0};
    print_area_and_point(c);
}

http://melpon.org/wandbox/permlink/TH9xztDKwDhjoyYz

Rust のポインタ

rust が提供するポインタは、以下の3つがあるらしい。

  • reference
  • Box
  • Rc/Arc

また、基本的なルールとして、リーダブル(immutable)なポインタは同時に複数作れて、ライタブル(mutable)なポインタは一度に一つしか作れない。 これをownershipとかいうらしい。 複数の人がかけたら、値が不定になるからそれを防ぐためのようだ。

3つのポインタはC++な人には、以下の対応付けで考えればわかりやすい。

rust c++
reference reference
Box std::unique_ptr
Rc/Arc std::shared_ptr

Rc と Arc の違いは、thread と組み合わせられるかどうか。 atomically reference counted の略らしい。 C++ の shared_ptr は thread 対応なのでカウンタのロックが必要でパフォーマンスが云々みたいな話があるが、 rust は用途別に用意したようだ。