rubyを使って擬似digコマンドをつくってみる
●まえがき
暇つぶしにつくりました
最小限の実装(パラメータ直打)となっています
需要はないと思いますが載せておきます
●実装及びテスト環境
Linux Mint 17.2 Rafaela 64-bit
ruby 2.2.1p85 (rvmで入れました)
net-dns ver.0.8.0 (モジュールです gem install net-dnsで入れました)
●実際に使った様子
このブログのURLを名前解決した結果です
キャッシュサーバにキャッシュがあるため、すぐ応答がきています
見方がわからない人は、DNS クライアントを作ってみよう (2)を見てみるといいかも
require 'socket' require 'rubygems' require 'net/dns' require 'benchmark' srcip = "127.0.0.1" #自身のIPアドレス sport = rand(1024..65535) #自身のポート番号(乱数) dport = 53 #宛先ポート番号(DNS => 53) dstip = "127.0.1.1" #DNSのIPアドレス seturl = "wiasth.hatenablog.com" #名前解決したいURL @udps = UDPSocket.open @udps.bind(srcip, sport) que = Net::DNS::Packet.new(seturl) @udps.send(que.data, 0, dstip, dport) time = Benchmark.realtime do @r = IO::select([@udps], nil, nil,5) end if @r res = @udps.recvfrom(1024) res = Net::DNS::Packet::parse(res) time = time*1000 time = time.round(10) puts "\n#{res}\n" puts ";; Query time: #{time} msec\n\n" else time = time*1000 time = time.round(12) puts "\n;; connection timed out: no servers could be reached\n" puts ";; Query time: #{time} msec\n\n" end @udps.close
わずか35行
やっていることは
1.パラメータのセット
2.Aレコードを作りDNSサーバへ送る
3.最大5秒間応答待ち、5秒たっても応答がなければ終了
4.応答があればそのパケットを表示する
の4つです
1.パラメータのセット
srcip = "127.0.0.1" #自身のIPアドレス sport = rand(1024..65535) #自身のポート番号(乱数) dport = 53 #宛先ポート番号(DNS => 53) dstip = "127.0.1.1" #DNSのIPアドレス seturl = "wiasth.hatenablog.com" #名前解決したいURL
プログラムに直接パラメータを打ち込んでいます
最低限動作させるだけならこれで十分だと思います
2.Aレコードを作りDNSサーバに送る
@udps = UDPSocket.open @udps.bind(srcip, sport) que = Net::DNS::Packet.new(seturl) @udps.send(que.data, 0, dstip, dport)
上の2行で自身のIPとUDPのポート番号をbindしています
下の2行では、セットしたURLを元にAレコードをつくりDNSサーバへ送信しています
※補足
que = Net::DNS::Packet.new(seturl)とは?
net-dnsというモジュールをつかうことで1行でレコードをつくっています
Packet.newのデフォルトはAレコードとなっているみたいです
他のレコードの作成の仕方として、例えば192.168.1.1を逆引きしたい(PTRレコード)ときは、
que = Net::DNS::Packet.new("192.168.1.1", Net::DNS::PTR)
でいけると思います(他のレコードも同じで、パラメータとNet::DNS::レコードの種類でいけるっぽい?)
3.最大5秒間応答待ち、5秒たっても応答がなければ終了
time = Benchmark.realtime do @r = IO::select([@udps], nil, nil,5) end ・ ・ ・ else time = time*1000 time = time.round(12) puts "\n;; connection timed out: no servers could be reached\n" puts ";; Query time: #{time} msec\n\n" end
上にあるtimeではbenchmarkという時間をはかるモジュールを使っています
囲っている部分の時間をはかれるようです
今回はパケットを送ってから応答が検出されるまでをはかっています(これで大丈夫なのかは分からない)
⇒ 追記;応答を受信したときの日時 - パケットを送信したときの日時 で時間を出した方が良かった
タイムアウトまでの時間はnslookupコマンドのデフォルトと同じ5秒としました
パケットを送ってから5秒の間@r(応答)が検出されなければif文のelseの方に入り、タイムアウトメッセージと送信から応答までの時間を表示して終わりとなっています
4.応答があればそのパケットを表示する
if @r res = @udps.recvfrom(1024) res = Net::DNS::Packet::parse(res) time = time*1000 time = time.round(10) puts "\n#{res}\n" puts ";; Query time: #{time} msec\n\n"
@r(応答)が検出されたらif文のifの方に入ります
ここでは、レスポンスのデータをNet::DNS::Packet::parseに格納することでレスポンス解析しています
net-dnsの仕様で「puts レスポンス」するだけで詳細表示されるようになっているみたいです
レスポンスの中身を表示し、送信から応答までの時間を表示して終わりとなっています
●応答時間テスト
digコマンドと比較してみました
計測方法:
1.dnsmasq(127.0.1.1)のキャッシュを一度クリア
2.dnsmasqに対して11回「wiasth.hatenablog.com」の名前解決要求
3.はじめの1回目をキャッシュ用とみなし破棄、2-11回目の応答時間結果を10で割る
1〜3の操作を両者で行ないました(こんなやり方で良いのかは疑問ですが)
digコマンドに合わせてmsecのコンマ以下は切り捨てとしました
結果:
digコマンド ⇒ 25.9msec
つくったやつ ⇒ 25.0msec
(環境次第な感じ?)
●最後に(補足等)
結果表示自体はdigコマンドのほうが今回つくったやつより早いです
理由としては、rubyでは結果表示(puts文等)がかなりのロスになるからです
応答時間のはかり方が正しいのかあやしい(プログラム的な意味で)ので、上記のテストはあまり参考にしないでください
間違えてる気がするので、テストは見なかったことにしてください
今回使用したnet-dnsモジュールを使うとrubyで簡単なDNSサーバを実装できます
net-dnsの他にDNS関連のモジュールでrubyDNSというものもありますが、個人的には今回使ったnet-dnsが使いやすく感じました
DNSで既存処理以外のことをさせたいというときにBINDに手を加えるよりはnet-dnsを使って実装したほうが楽な気がします
しかしながら、net-dnsは情報が少ないみたい(ぐぐってもあんまりでてこない)なので、機会があれば載せてみようと思います
以上
ローカルネットワーク内のみで使えるメールサーバをたてよう
●はじめに
・外部には公開せず、ローカルネットワーク内のみの検証用としてメールサーバをたてたい
・とりあえずメールサーバをたててみたいが、どうすればよいか分からない
このような人向けです
※設定ファイルに余計な設定をしてしまっているところがあったり、説明が間違えているところがあるかもしれません
また、2014/12月時点での導入方法なので、バージョンがあがるなどの環境の変化によりこの方法ではできなくなってしまうかもしれません、ご了承ください
●今回紹介するメールサーバ導入の概要
最終的には以下のような構成になります(仮想環境です)
・前提
1.VMwarePlayerにメールサーバ兼クライアントとしてCentOS6.6を、クライアントとしてLubuntu14.10をたて終わっている
2.SSLなどのセキュリティ機能は使わない
3.DNSを使用せず、サーバを指定するときは直接IPアドレスを指定する
・目標
server1(server1@example.local)、user1(user1@example.local)というアカウントをつくり、メールクライアントを用いてローカルネットワーク内でメールのやり取りをする
・環境
1.VMwarePlayer 6.0.2
2.CentOS 6.6 (メールサーバ兼クライアント用)
3.Lubuntu 14.10 (クライアント用) ※クライアント用はどんなOSでもよい
4.Postfix 2.6.6-6 (メール送信サーバ) プロトコルとしてSMTPを使っている
5.Dovecot 2.0.9-8 (メール受信サーバ) プロトコルとしてIMAPかPOPを使っている ⇒今回はIMAPを使う
6.Evolution 2.32.3-34 (メールクライアント) ← マイクロソフト社のOutlookのようなもの
●viエディタの簡単な使い方(必要のない方は飛ばしてください)
今回、設定などを編集するのにviエディタ(ウィンドウズでいうメモ帳のようなもの)を使う
このviエディタを使う上で重要なことは、Insertキーを押すと挿入モードに、Escキーを押すとコマンドモードになるということ(だと思う)
例
・文字を書きたかったら →Insertキーを押すと書けるように
・ファイル上書きしたかったら →Escキーを押す、:w を入力しエンター
・編集を終了したかったら →Escキーを押す、:q を入力しエンター
・ファイルを上書きせず編集を終了したかったら →Escキーを押す、:q! を入力しエンター
今回はこの程度の知識があれば十分です
●流れ
1.いきなり構成通り設定するのではなく、はじめにメールサーバ兼クライアント(CentOS)内でメールのやり取りができるようにする
2.メールサーバ用CentOS及びクライアント用Lubuntuの持つインターフェースにIPアドレスを割り振り、IP通信ができることを確認する
3.192.1.1.0/24内でもメールを使えるように設定を少しいじる
4.メールサーバ用CentOSとクライアント用Lubuntu間でのメールのやり取りをテストし、無事動作したら目標達成
●手順1
概要:メールサーバ兼クライアント(CentOS)内でメールのやり取りをできるようにする
メールサーバ兼クライアント(CentOS6.6)を起動、ターミナルを開く
以下のコマンドを実行
su ←rootにする
yum -y update ←念のためアップデート
vi /etc/selinux/config
SELINUX=enforcing
⇒ SELINUX=disabled に変更(selinuxを無効化)
(※viエディタの使い方は少し上の項目にあります)
次に、使用するポート番号のファイアウォールを無効化する
a.システム→管理→ファイアウォールを選ぶ
b.ファイアウォールの設定画面が開くと以下のようなポートリストがでるので、メール(SMTP)にチェック
c.次にその他のポートを選ぶ
d.右側にある追加ボタンを押し、ポート番号110番のpopとポート番号143番のimapのtcp,udpをリストに追加
e.以下の画面のようになったら、最後に適用ボタンを押し反映させる
上記の作業が終わったら、一旦CentOSを再起動する
・postfix関連から設定
su ←rootにする
yum -y install postfix ←postfixのインストール(元から入っているかも)
service sendmail stop ←Sendmailを止める(そもそも入ってないかも)
chkconfig sendmail off ←Sendmail自動起動を止める(そもそも入ってないかも)
service postfix start ←postfixを起動
chkconfig postfix on ←postfix自動起動を有効化
・設定ファイルの編集
vi /etc/postfix/main.cf
#mydomain = domain.tld
⇒ mydomain = example.local に変更(#をはずしドメイン名変更 自分のドメイン名を書くところ)
#myorigin = $mydomain
⇒ myorigin = $mydomain に変更(#はずす)
inet_interfaces = localhost
⇒ inet_interfaces = all に変更(localhostのみしか受け付けなくなっているため変更)
inet_protocols = all
⇒ inet_protocols = ipv4 に変更(今回はIPv4しか使わないため変更)
mydestination = $myhostname, localhost.$mydomain, localhost
⇒ mydestination = $myhostname, localhost.$mydomain, localhost, example.local に変更(宛先ドメインとして今回使うドメイン名を追加しておく)
#mynetworks = ・・・の下
⇒ mynetworks = localhost を追加(はじめはlocal内で動かすだけなので自分のネットワークはlocalhostのみ)
#home_mailbox = Maildir/
⇒ home_mailbox = Maildir/ に変更(#はずす メールボックスはMaildir形式を使うようにするという意味)
これで /home/ユーザ名/Maildirに保存されるように?
#mail_spool_directory = /var/mail
⇒ mail_spool_directory = /var/mail/ に変更(#はずし、/追加 各ユーザのメールディレクトリは/var/mail/以下につくるという意味)これやらなくていいかも
設定を保存し編集を終えたら、
service postfix restart でpostfixを再起動
・メールアカウントをつくる(今回はuser1とserver1)
useradd user1 -s /sbin/nologin ←user1ユーザの追加
passwd user1 ←user1のパスワード登録(今回は「12345」としました)
useradd server1 -s /sbin/nologin ←server1ユーザの追加
passwd server1 ←server1のパスワード登録(今回は「12345」としました)
後でパスワードを使うことになるので覚えておく
※今回は説明をしやすくするため、パスワードを「12345」としましたが、これは破られやすいパスワードなので必ず推測されにくいパスワードを使ってください
・user1やserver1は/var/spool/mail/以下の書き込み権がないので権限を与える
chmod 777 /var/spool/mail
以上でメール送信はできるようになったので、telnetというターミナル上でメールなどのやり取りができるものを使ってメール送信テストを行なう
yum -y install telnet ←telnetのインストール
telnet localhost 25 ←ポート25番にlocalhostで接続
220 localhost.localdomain ESMTP Postfix
helo localhost
250 localhost.localdomain
mail from: user1@example.local ←メールの送信元アドレス
250 2.1.0 Ok
rcpt to: user1@example.local ←メールの宛先アドレス
250 2.1.5 Ok
data ←メールの本文かきますよというコマンド
354 End data with <CR><LF>.<CR><LF>
helo postfix ←メールの本文
. ←コンマはメールの本文を書き終えましたよというコマンド
250 2.0.0 Ok: queued as ・・・
quit ←telnetを終了するコマンド
221 2.0.0 Bye
このテストが終わった後
ls /var/mail/user1 でファイルができていることを確認
ls /home/user1/Maildir でファイルができているはず(ディレクトリが見つからないとでなければ問題なし)
・dovecot関連の設定
yum -y install dovecot ←dovecotのインストール
service dovecot start ←dovecotを起動
chkconfig dovecot on ←dovecot自動起動を有効化
・設定ファイル(dovecot.conf)の編集
vi /etc/dovecot/dovecot.conf
#protocols = imap pop3 lmtp
⇒ protocols = imap pop3 lmtp に変更(#はずす 使用プロトコルの列挙)
#listen = *, ::
⇒ listen = * に変更(#はずし、::消す 今回はIPv4しか使わないので::(IPv6)へのバインドをしない)
・設定ファイル(10-mail.conf)の編集
vi /etc/dovecot/conf.d/10-mail.conf
#mail_location =
⇒ mail_location = maildir:~/Maildir に変更(#はずし、ファイル場所をかく)
・設定ファイル(10-auth.conf)の編集
vi /etc/dovecot/conf.d/10-auth.conf
#disable_plaintext_auth = yes
⇒ disable_plaintext_auth = no に変更(#はずし、noにする 平文認証の許可)
auth_mechanisms = plain
⇒ auth_mechanisms = plain login に変更(login追加 いらないかも?)
設定を保存し編集を終えたら、
service dovecot restart でdovecotを再起動
以上でメール受信できるようになったので、telnetを使ってターミナル上でメール受信ファイルを見るテストを行なう(IMAPを使う)
telnet localhost 143 ←ポート143番にlocalhostで接続
※1、2などの数字も忘れずに
Connected to localhost.
1 login user1 12345 ←「1 login ユーザー名 パスワード」でログインする
Logged in
2 list "" * ←ホームディレクトリの一覧を見るコマンド(""の後半角空白あり)
* List () "." "INBOX"
2 OK List completed.
3 select INBOX ←INBOXの中身を見るコマンド
1 EXISTS ←1通のメールがある
1 RECENT ←最新のメールは1通
3 OK Select completed.
4 fetch 1 body[] ←1通目のメールを見るコマンド(送信テストしたものが見れる)
From: user1@example.local
To: undisclosed-recipients:;
helo postfix
)
4 OK Fetch completed.
5 logout
5 OK logout completed.
テスト完了
・Evolutionというメールクライアントを使って送受信テストする
yum -y install evolution ←evolutionをインストール
インストール後、アプリケーション→オフィス→Evolutionを選ぶ
設定画面がでてくるので、2回進むを押す
以下の画面でuser1の情報を登録、追加情報の下にあるボックスのチェックをはずす
この画面では、サーバ指定欄に「127.0.0.1」を指定しておく
この画面でも、サーバ指定欄に「127.0.0.1」を指定しておく
適用ボタンを押した後、IMAPを使うためのパスワードをきかれるので、作成したアカウントのパスワードを入れる(今回ならuser1、server1ともに「12345」)
evolutionのタブの編集→設定を選ぶ
設定画面がでたら、右側にある追加ボタンを押し、server1についても先ほどと同じ設定を行なう
設定が終わったら、evolutionのタブの表示→現在のビューのメッセージ表示にチェック、またスレッドでグループ化にもチェックを入れる
次にevolutionのタブの表示→配置の3つの項目すべてにチェックを入れる
すると、左側にサイドバーができる
まず、server1からuser1へテストメールを送ってみる
左側サイドバーのserver1@example.localを選択し、新規ボタンを押す
以下の画面のようなメールを書き、送信ボタンを押す
左側サイドバーの送信済みを選択し、先ほど書いたメールがあれば成功
次にテストメールをuser1が受信できているか確認する
左側サイドバーのuser1以下の受信箱を選択し、以下のようにテストメールが届いていれば成功
メールサーバ兼クライアント(CentOS)内でメールのやり取りをできるようになった
●手順2
概要:CentOS、Lubuntuの持つインターフェースにIPアドレスを割り振り、IP通信ができることを確認する
・一旦CentOSをシャットダウンし、VMwarePlayerを開く
a.CentOSを選択し、右下の仮想マシン設定の編集ボタンを押す
b.設定画面の下の方にある追加ボタンを押しネットワークアダプタを選択
c.次へボタンを押し、そのまま完了ボタンを押す
d.ネットワークアダプタ2を選択し、カスタムにチェック
e.今回はVMnet19を使用するため、VMnet19を選択
f.設定が終わったら下の方にあるOKボタンを押し反映させる
・Lubuntuについてもa~fを行なう
・CentOS側からIPアドレスの設定を行なう
CentOSを起動する
システム→設定→ネットワーク接続を選択
Auto eth1(もしかしたらeth0かも)を選び編集ボタンを押す これはインターネット(NAT)につなぐインターフェースなので、接続名をinternetとし適用ボタンを押す
次にAuto eth2(もしかしたらeth1かも)を選び編集ボタンを押す これはVMnet19につなぐインターフェースなので、接続名をVMnet19とし、IPv4のセッティングタブを押す
方式を手動に、右側にある追加ボタンを押し、IPアドレス、ネットマスク、ゲートウェイをページ一番上にあるネットワーク構成図を参考に以下のように割り振り、適用ボタンを押す
以上でインターフェースの設定は終わったので、閉じるボタンを押し、再起動して設定を反映させる
・次にLubuntu側のIPアドレスの設定を行なう
Lubuntuを起動する
左下のスタートボタン→設定→ネットワーク接続を選択
Wired connection1を選び編集ボタンを押す これはインターネット(NAT)につなぐインターフェースなので、接続名をinternetとし保存ボタンを押す
この時、internetが2つできてしまうが、設定はしっかりとできているので無視してよい
次にWired connection2を選び編集ボタンを押す これはVMnet19につなぐインターフェースなので、接続名をVMnet19とし、IPv4設定タブを押す
方式を手動に、右側にある追加ボタンを押し、IPアドレス、ネットマスク、ゲートウェイをページ一番上にあるネットワーク構成図を参考に以下のように割り振り、保存ボタンを押す
以上でインターフェースの設定は終わったので、閉じるボタンを押し、再起動して設定を反映させる
・pingでIP通信ができることを確認する
CentOS側のターミナルで ping 192.1.1.2 を実行
64 bytes from 192.1.1.2: ・・・・ と応答が返ってくれば成功
次に、Lubuntu側のターミナルで ping 192.1.1.1 を実行
64 bytes from 192.1.1.1:・・・・ と応答が返ってくれば成功
※もしうまくいかなかった場合
CentOS、Lubuntu両方でifconfigコマンドを実行する
これはインターフェースの情報が見られるコマンドとなる
CentOS側:eth1の項目にinet addr:192.1.1.1があることを確認
Lubuntu側:eth1の項目にinetアドレス:192.1.1.2があることを確認
⇒なければIPアドレスがしっかりと振れていない可能性があるので、ネットワーク接続設定画面を開き、設定されてなければ設定し、再起動する
●手順3
概要:192.1.1.0/24内でもメールを使えるようにする
・まずはpostfixから設定
CentOS側のターミナルで以下を実行
su
vi /etc/postfix/main.cf
mynetworks = localhost
⇒ mynetworks = localhost, 192.1.1.0/24 に変更(自分のネットワークにVMnet19を加える)
service postfix restart ←postfixを再起動
・dovecotのdovecot.confの編集
vi /etc/dovecot/dovecot.conf
#login_trusted_networks =
⇒ login_trusted_networks = 192.1.1.0/24 に変更(#をはずし、ネットワークアドレスをかく 必要ないかも?)
service dovecot restart ←dovecotを再起動
以上で設定終わり
●手順4
概要:CentOSとLubuntu間でのメールのやり取りをテストする
・Lubuntu側のターミナルで以下を実行
sudo apt-get update ←一応アップデートしておく
sudo apt-get install evolution ←evolutionのインストール
左下にあるスタートボタン→オフィス→Evolutionを選択
アカウント設定画面がでるので、以下の画面まで続行ボタンを押す
以下の画面では、user1の情報を登録し続行ボタンを押す
次の画面では、以下のようにサーバー指定欄に「192.1.1.1」を指定し、ユーザー名をuser1とする
(次の画面:新着メールをチェックする周期は10分ぐらいにしておくといいかも)
以下の画面で、サーバー指定欄に「192.1.1.1」を指定しておく
アカウントの設定が完了するとパスワードをきかれるので、登録したユーザ名のパスワード(今回ならuser1のパスワード「12345」)を入力する
次に新しいキーリングのパスワードの指定を聞かれるが、これも登録したユーザ名のパスワードで良い(と思う)
・最後にメールの送受信テストをする
1.user1(Lubuntu側)からserver1(CentOS側)にテストメールを送る
メールの作り方はメールサーバ内でやった時と同じなので省略
Lubuntuのuser1アカウントでserver1へテストメールを送り、CentOSのserver1
の受信箱に来ていれば成功
2.server1(CentOS側)からuser1(Lubuntu側)にテストメールを送る
CentOSのserver1アカウントでuser1へテストメールを送り、Lubuntuのuser1の受信箱に来ていれば成功
もしすぐ届いてないようだったら、上にある送信/受信ボタンを押せばメールがくるはず、それでもこなければevolutionを一度閉じてまた起動すればくると思う
以上で、目標通り、メールクライアントを用いてローカルネットワーク内でメールのやり取りができました
今回は、メールサーバをたてるための簡単な知識を取得するorローカルネットワーク内での検証用にメールサーバをたてるという目的を前提としているので、SSLなどのセキュリティ機能は使っていません
ですので、社内メールサーバとして運用したり、外部にメールサーバとして公開し運用するなど、正式なものとして運用する場合はセキュリティ機能も必ず設定してください
お疲れ様でした
simple-router 複数スイッチ対応 メモ (Trema 0.4.7)
こんな人向けのメモ
1.Tremaのサンプルについてくるsimple-routerの動作は理解している
2.スイッチ1つでsimple-routerの動作確認済
→スイッチ2つ以上でsimple-routerを動かしたいが、うまくいかない人
●テスト環境(仮想) OpenFlow1.0
・VMware
・Lubuntu 14.10
・Trema 0.4.7
・OpenvSwitch 2.3.0
(Tremaについてくる仮想ネットワークや仮想スイッチは使用していません)
●はじめに
Tremaのサンプルでついてくるsimple-routerはスイッチが1つの場合を想定しているため複数スイッチではうまく動作しません
従ってソースコードに手を加える必要があります
●例として以下のNW図のネットワークを作成
(Pはポート番号、eth後のカッコ内はMACアドレスの末尾を示している)
●まずはOpenvswitch端末側の設定から(必要のない方は読まなくても問題ありません)
・Openvswitch1(SW1)の設定
ターミナルで以下を実行
1.sudo ovs-vsctl add-br eth1
ブリッチの設定(コントローラにつながっているインターフェース名をいれる)
2.sudo ovs-vsctl add-port eth1 eth2
3.sudo ovs-vsctl add-port eth1 eth3
ブリッチにeth2とeth3をつなげる
4.sudo ovs-ofctl show eth1
ポート番号の割り振りを見ることができる
Port1がeth2,Port2がeth3になっていることを確認
5.sudo ovs-vsctl set bridge eth1 other-config:datapath-id=0000000000000001
※0が15個、1が1個の16ケタ
DPID(スイッチの番号)を分かりやすい番号に変更(しておいたほうが今後楽)
6.sudo ovs-vsctl get bridge eth1 datapath-id
DPIDが"0000000000000001"(0が15個、1が1個の16ケタ)になっていることを確認
7.sudo ovs-vsctl set-controller eth1 tcp:192.1.10.1:6653
コントローラに接続(コントローラのインターフェースのIP+TCPのポート番号(6653)入れる)
※現在、コントローラで使用するTCPのポート番号は6653で良いそうです
8.sudo ovs-vsctl show
Bridgeにeth1、Portにeth1(internal),eth2,eth3がついているのを確認
・Openvswitch2(SW2)も同様の設定を行なう
ただし5では
5.sudo ovs-vsctl set bridge eth1 other-config:datapath-id=0000000000000002
と、DPID = 2にする
最後にsudo ovs-vsctl showで見るとSW1と同じ構成になっているはず
●本題のsimple-routerのソースコードいじりに入る前に
Tremaのsimple_routerファイルを/local/ユーザー名/以下にコピー
(作業しやすくする、元ソースを残しておくため)
sudo cp -r /var/lib/gems/2.1.0/gems/trema-0.4.7/src/examples/simple_router /home/ユーザー名/
(cp -r コピーしたいディレクトリ コピー先ディレクトリ でディレクトリごとコピーできる)
●スイッチ2つ以上用のsimple-routerのソースコード
ソースに手を加える理由は、DPID(スイッチの番号)がないと一意にエントリを決めることができない場合があるためです
●まずconfファイルの変更を行なう
$interfaceと$routeにそれぞれdpidの要素を加える(以下、赤字が追加部分)
・$interfaceにはdpid1のport1,port2、dpid2のport1,port2をそれぞれ入力
$interface = [
{
:dpid => 1,
:port => 1,
:hwaddr => "XX:XX:XX:XX:XX:51",
:ipaddr => "192.168.1.1",
:masklen => 24
},
{
:dpid => 1,
:port => 2,
:hwaddr => "XX:XX:XX:XX:XX:5B",
:ipaddr => "192.168.10.1",
:masklen => 24
},
{
:dpid => 2,
:port => 1,
:hwaddr => "XX:XX:XX:XX:XX:A1",
:ipaddr => "192.168.2.1",
:masklen => 24
},
{
:dpid => 2,
:port => 2,
:hwaddr => "XX:XX:XX:XX:XX:AB",
:ipaddr => "192.168.10.2",
:masklen => 24
}
]
・$routeにはスイッチ間を行き来するためだけのテーブルをかく
simple-router.rbのresolve_next_hopメソッドをみれば分かるが、interface変数が見つからない場合、つまり自スイッチに宛先ホストがついていない場合のみ$routeを使うのでSW-host間の情報は$routeには必要なし
$route = [
{
:dpid => 1,
:destination => "192.168.2.0",
:masklen => 24,
:nexthop => "192.168.10.2"
},
{
:dpid => 2,
:destination => "192.168.1.0",
:masklen => 24,
:nexthop => "192.168.10.1"
}
]
●interface.rb
・読み込みと初期化メソッドにdpidの要素を追加
1.class Interfaceの下
attr_reader :dpid を追加
2.initializeメソッド
@dpid = options[:dpid] を追加
・DPIDの情報がないと一意にエントリが決まらない検索用のメソッドにdpidの要素を追加
3.find_by_portメソッド
def find_by_dpid_and_port(dpid, port) メソッド名の変更
each.dpid == dpid && each.port == port 条件の変更
4.find_by_prefixメソッド
def find_by_dpid_and_prefix(dpid, ipaddr) メソッド名の変更
each.dpid == dpid && each.ipaddr.mask(masklen).to_s == ipaddr.mask(masklen).to_s 条件の変更
●routing-table.rb
・初期化メソッドのHashを3次元ハッシュにする、add,delete,lookupメソッドのキーにdpidの要素を追加
1.initializeメソッド
@db = Array.new(ADDR_LEN + 1) { Hash.new ({}) } 3次元ハッシュ化
2.addメソッド
dpid = options[:dpid] 追加
@db[dpid][masklen][prefix.to_i] = Pio::IPv4Address.new(options [:nexthop]) キーにdpidを追加
3.deleteメソッド
dpid = options[:dpid] 追加
@db[dpid][masklen].delete(prefix.to_i) キーにdpidを追加
4.lookupメソッド
def lookup(dpid, dest) dpidの追加
entry = @db[dpid][masklen][prefix.to_i] キーにdpidの追加
●simple-router.rb
・必要な引数を追加
1.packet_inメソッド
return unless to_me?(dpid, message) dpidを追加
2.to me?メソッド
def to_me?(dpid, message) dpidを追加
interface = @interfaces.find_by_dpid_and_port(dpid, message.in_port) に変更
3.handle_icmpv4_echo_requestメソッド
interface = @interfaces.find_by_dpid_and_port(dpid, message.in_port) に変更
4.forwardメソッド
next_hop = resolve_next_hop(dpid, message.ipv4_daddr) dpidを追加
interface = @interfaces.find_by_dpid_and_prefix(dpid, next_hop) に変更
5.resolve_next_hopメソッド
def resolve_next_hop(dpid, daddr) dpidを追加
interface = @interfaces.find_by_dpid_and_prefix(dpid, daddr.value) に変更
@routing_table.lookup(dpid, daddr.value) dpidを追加
●実行する場合
cd /home/ユーザー名/simple_router
sudo trema run simple-router.rb を実行
host1側から ping 192.168.2.2
host2側から ping 192.168.1.2
を実行し、期待通り動作しているのを確認
●うまくいかなかった方へ
はじめに、confファイルにミスがないか見ると良いと思います
次にメソッド名のミス、引数が足りない(特に今回追加したdpidの書き忘れ)、割り当てたIPアドレスが間違えている等を確認
●それでもうまくいかなければ
どこのメソッドでエラーを吐いているか見るため、それぞれのメソッドのdefの下にinfo(printと同じです)を追加する
例 to_me?メソッドの下に info "[info]to_me?" と追加
こうすることで、パケットインで上がってきたパケットが通ったメソッドを知らせてくれるので、どこでエラーを吐いているのか分かると思います
●最後に
今回は追加部分だけを記載しました(追加理由は考えれば分かると思うので)
http://uploader.83net.jp/1142100770510357133873
作成したsimple-routerはこちらでアップしています
パスは「wiasth」です(ドラッグで見れます)
OpenFlow Trema0.4.7 のインストール メモ
追記(2016/1月);tremaの最新バージョンが変わったようなので、0.4.7をインストールできるように説明を変えました
ググってもうまくできるものがなかったので記載
(OpenFlow1.0なのでもう着手する人がいない模様?)
2014/11/25現在はこの方法でいけました
環境が違う場合、この方法ではインストールできないかもしれないので参考程度にお願いします
・環境
VMwarePlayer
Lubuntu 14.10
・以下、Tremaを入れる予定の端末のターミナルで実行
1.sudo apt-get update
とりあえずアップデート
2.sudo apt-get install git gcc make ruby ruby-dev libpcap-dev libsqlite3-dev libglib2.0-dev
Tremaのインストールに必要なもののインストール
3.sudo gem install rubygems-update
rubygemsは-updateをつけないとうまくインストールできない模様
4.sudo gem update
gemにあるものをアップデート
5.sudo gem install trema -v 0.4.7
追記; バージョン指定オプションを使って0.4.7を指定すること
/usr/include/ruby-2.1.0/ruby/config.hがないという内容のエラーが出る(はず)
なぜかconfig.hは別の場所にインストールされているみたいなので、その場所を探す
6.sudo find / -name config.h
config.hは /usr/include/x86_64-linux-gnu/ruby-2.1.0/ruby/以下にあるという結果がでる(と思う)
config.hが本来あるべき場所にコピーする
7.sudo cp /config.hのあるディレクトリ/config.h /エラーがでたファイル/ でコピーできる(cp /config.hの後に半角スペースが入っている)
例えば、config.hのある場所が/usr/include/x86_64-linux-gnu/ruby-2.1.0/ruby/以下で、エラーを吐いた場所が/usr/include/ruby-2.1.0/ruby/だった場合
sudo cp /usr/include/x86_64-linux-gnu/ruby-2.1.0/ruby/config.h /usr/include/ruby-2.1.0/ruby/
8.コピー後、再度 sudo gem install trema -v 0.4.7 をするとうまくいく(はず)
9.sudo trema -v でバージョン等の情報が表示されれば成功
あ
作業をしていてググったものではうまくいかなかったものや見つからなかったことを記載しています
よければ参考にしてください