V6プラス環境で、ラズパイでPPPoE接続

V6プラス環境では、IPoEで割り振られるIPv4アドレスは、契約者に割り振られた部分的なポート番号しか使えません。
サーバを公開したくなったので、全てのポートが使えるIPv4アドレスが欲しくなりました。

なのでHGWの下に配置したラズパイでPPPoE接続をします。

(この記事では、ラズパイの内部「以外」のサーバ公開まではしていません。この記事の手順だけで、ラズパイで立てているサーバは公開できます。)

概念図

NTTから貸与されているHGW (PR-500KI)とRaspberry Piを使います。
HGWでIPoE接続で IPv6とIPv4を使います。
その配下にRaspberry Piを置き、HGW越しに IPv4 PPPoE接続をします。

こうすればラズパイに、全ポートが使えるIPv4アドレスが割り振られます。

HGW ( PR-500KI )の設定

設定画面(http://192.168.1.1)にアクセスし、PPPoEブリッジが有効なことを確かめます。デフォルトでは有効です。

Raspberry Piの設定

まずPPPoE関連のパッケージをインストールします
sudo apt-get install pppoe pppoeconf

/etc/ppp/peers/dsl-provider ,
/etc/network/interfaces ,
/etc/ppp/*-secrets
の3つのファイルをバックアップしておきましょう。PPPoEの設定をすると書き換えられます。

次のコマンドでPPPoEの設定を開始します。
私は全部「ハイ」を選びました。ISPからもらったPPPoE接続用のIDとパスワードを入力しましょう。

pppoeconf

設定できたら、PPPoEでちゃんと接続できたか調べてみましょう。IPアドレスが割り振られていたら成功です。

ip addr show ppp0

自分がやったときはここまでの手順でも外からだと通信できなくて、ルーティングテーブルをいじくったりしました(このページの最後にコメントアウトされています)
けど、デフォルト設定のままでも放っておいたらできたので、あとは何もしなくても使えるようです。

ここまでの設定で、ラズパイ上のサーバは公開できます。
ラズパイがインターネットに直接晒されるので、セキュリティ関係はしっかりやっといてください。

以下は例です。この例ではどんな通信もファイアウォールによりチェックされることになりますが、PPPoEを使った通信だけを対象としても良いと思います。

sudo apt-get install ufw      #ufwというソフトウェアファイアウォールをインストール
sudo ufw status               #ufwの状況を見る
sudo ufw enable               #ufwを起動時に有効化するように設定
sudo ufw deny                 #デフォルトのルールをdenyにする(許可するものだけ追加していくスタイルになる)

sudo ufw allow 80             #ポート80を許可
sudo ufw limit 22             #ポート22を制限付き(一定時間内に同じ送信元からアクセスしてきたらそいつを遮断)で許可

sudo ufw status verbose       #どういうルールになっているか確認する

Pythonで連分数展開

連分数展開。CTFのCrypto問で必要になりました。
Python3でしか動作確認していません。
Wikipedia: 連分数をご覧ください。

コード中のexpand_to_continuous_fraction(a, b)は、下の画像でいうx=a/bとしたときの[a0, a1, a2, …]を返す関数。


(画像はWikipedia: 連分数より引用)

コード中のcontract_from_continuous_fraction(list_a)は、「連分数の性質」とやらにより下の画像でいう[(p0,q0), (p1, q1), …]を返す関数。



(画像はWikipedia: 連分数より引用)


実行結果

>>> print (expand_to_continuous_fraction(42,11) )
[3, 1, 4, 2]
>>> print ( contract_from_continuous_fraction(expand_to_continuous_fraction(42,11) ) )
[(1, 0), (3, 1), (4, 1), (19, 5), (42, 11)]

スクリプト

# -*- coding: utf-8 -*-

#a/bを連分数展開する
def expand_to_continuous_fraction(a, b):
    answer = []
    next_a = a
    next_b = b
    for i in range(100000):
        c_a = next_a
        c_b = next_b
        if c_b == 0:
            break
        current_num = c_a//c_b
        
        answer.append(current_num)
        temp_next_a = c_a - current_num*c_b
        
        next_a = c_b
        next_b = temp_next_a
    return answer

#連分数展開した結果をもとに、それをp/qという分数の形にしていく
def contract_from_continuous_fraction(list_expanded_continuous_fraction):
    l_p =[1, list_expanded_continuous_fraction[0]]
    l_q =[0, 1]
    list_expanded_continuous_fraction.pop(0)
    for ind_c_a, c_a  in enumerate(list_expanded_continuous_fraction):
        ind_pq = ind_c_a + 2
        l_p.append(c_a * l_p[ind_pq -1] + l_p[ind_pq -2])
        l_q.append(c_a * l_q[ind_pq -1] + l_q[ind_pq -2])

    answer = []

    for ind_pq in range(len(l_p)):
        answer.append( (l_p[ind_pq], l_q[ind_pq])  )

    return answer

print (expand_to_continuous_fraction(42,11) )
print ( contract_from_continuous_fraction(expand_to_continuous_fraction(42,11) ) )