matplotlibで3次元グラフを描く

# Jupyter Notebook で描く場合
%matplotlib inline

import numpy as np
import matplotlib.pylab as plt
from mpl_toolkits.mplot3d import Axes3D

def function_2(x):
    return x[0]**2 + x[1]**2

x = []
x.append(np.arange(-3.0, 3.0, 0.2))
x.append(np.arange(-3.0, 3.0, 0.2))

mg_0, mg_1 = np.meshgrid(x[0], x[1])
y = function_2([mg_0, mg_1])

fig = plt.figure()
ax = Axes3D(fig)
ax.plot_wireframe(mg_0, mg_1, y)
plt.show()

f:id:uchida75cm:20180721204154p:plain

"RH-Firewall-1-INPUT"って何だっけ?

iptablesの設定って基本的なことはわかってたつもりでしたが、改めて調べるとiptablesってけっこういろんなことができるんですね^^;)
これまでiptablesは全部「INPUT」で書くか、デフォルトと同じように「RH-Firewall-1-INPUT」にフィルター追加すれば動いてたのであんまり気にしなかったけど、「RH-Firewall-1-INPUT」ってなんだっけ?と思ったのがきっかけです。
調べてみてわかったことを書こうと思います。

参考にしたのはこちら。

その1 チェインって自分で定義できるんですね!

記事のタイトルにもあるやつですが、RH-Firewall-1-INPUTは独自に追加したチェイン名で、名前は何でもいいようです。自分で追加できるとは知りませんでした。
下記のように、自分で新しくチェインを定義して、INPUTもFORWARDも同じポリシーに従うように設定できる、というのがメリットみたいです。

:RH-Firewall-1-INPUT -
-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT

その2 ネットワークのインターフェイスで絞り込むこともできるんですね!

下記は、lo(ローカルループバック)のアクセスは許可の意味になりますが、eth0などifconfigで出力されるインターフェイスに限定して設定を追加できる。

-A RH-Firewall-1-INPUT -i lo -j ACCEPT

その3 なんとなく使ってた-m(拡張モジュール)

--sport, --dport という記述はこれまで何となく使っていましたが、ハイフンひとつで記述するオプションとは別(考えてみれば当然^^;)。
-mは拡張モジュールを指定するオプションで、tcp, udp, stateといった拡張モジュールのオプションがハイフンふたつのオプション。
tcp, udpの拡張モジュールを使うと、出元ポートや宛先ポートでパケットを絞り込める。stateはNEW、ESTABLISHED、RELATED、INVALIDなどを指定して、パケットの過程によってフィルタリングできる(接続開始パケットは許可する など)。

-A RH-Firewall-1-INPUT -p tcp -m tcp --sport 67:68 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --sport 67:68 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

その他

デフォルトで書かれてたりする下記の記述ですが、--reject-withを指定するとリジェクトしたときのエラー内容を指定できるよう。

-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited

これも今まで気にしていなかったんですが、各行の[0:0]などの記述は統計情報になっているらしく、各フィルターを通過した[パケット数:バイト数]になっているみたいです。iptables-saveで/etc/sysconfig/iptablesに設定が書き込まれた場合などに出力される。

とまあ知ってるつもりだったことも、改めて調べるといろいろわかりますね^^;)これからも精進します。

nginxで502エラーが出てヘッダーがでかいと言われる

c4saのnginxで「502 Bad Gateway」というエラー画面が表示され、error.logに下記のメッセージ。

upstream sent too big header while reading response header from upstream

調べてみると下記のページが見つかった。

素直に、nginxの先頭に下記の設定を追加

fastcgi_buffers 8 16k;
fastcgi_buffer_size 32k;

問題なく動作するようになりました。

Expressでログイン機能を作る

MacOSX上で、nvmを使ってインストールしたnode.js v0.4.9の環境です。

まず細かい設定はせずに、ざっくりとた例です。Expressのセッションサポートについてはこちらに記載されています。そのまま設定するとこんな感じ。

app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));

上記の設定をすると、req.sessionという値が利用できるようになります。ルーティングの例。

app.get('/', function(req, res){
  if (req.session.flg) {
    res.render('index');
  }
});

アクセスしただけでセッションidは発行されますが、セッションを張っただけでは、req.session.flgという値は無いのでページは見れません。idとpasswdの認証が通った後などに設定してあげる必要があります。

var id = 'foo';
var passwd = 'hoge';

app.post('/check', function(req, res) {
    if(id === req.body.id && passwd === req.body.pw) {
      req.session.flg = true;
      res.redirect('/');
    } 
});

テンプレートはこんな感じ。

h1= title
p Welcome to #{title}
h1= title
p Enter your id & pw 
form( method='POST', action='/check')
  input( type='text', name='id' )
  input( type='password', name='pw' )
  input( type='submit', name='enter', value='login' )

とりあえずこれだけで、ログインぽいものはできました。

デフォルトのまんまだとセッション情報は...メモリ上? にあるのかな。だとなんか不安なので、セッションストアを利用します。ドキュメントだとRedisがススメられていますが、アプリケージョンの情報はMongoDBを使っているので、セッションストアにもMongoDBを使いたいのです。使うとこんな感じです。

var Db = require('mongodb').Db;
var Server = require('mongodb').Server;
var server_config = new Server( 'localhost', 27017, {auto_reconnect: true, native_parser: true});
var db = new Db( 'authtest', server_config, {} );
var mongoStore = require( 'connect-mongodb');
var auth;
  app.use(express.cookieParser());
  app.use(express.session({
    cookie: {maxAge: 60000 * 20},
    secret: 'foo',
    store: auth = new mongoStore({db: db})
  }));

これで、セッションの置き場がMongoDBに置き換えられました。確認してみましょう。

$ mongo
MongoDB shell version: 1.8.0
connecting to: test
> use authtest
switched to db authtest
> db.sessions.find();
{ "_id" : "fWBduKOKEq0rnHc5YWp7UBQ3.uCg+n9B8B0Kx6KxPK7AaixqSrCArGGIgl3EAkiKm4+M", "session" : { "lastAccess" : NumberLong("1310397363006"), "cookie" : { "originalMaxAge" : 1200000, "expires" : "2011-07-11T15:36:03.007Z", "httpOnly" : true, "path" : "/" } }, "expires" : NumberLong("1310398563000") }
>

セッションストアを利用して認証状態を確認するときはこんな感じになるかと思います。

app.get('/', function(req, res){
  auth.get(req.session.id, function(err, sess) {
    if(sess && sess.views) {
      res.render('index', {
        title: req.session.userid
      });
    } else {
      res.redirect('/login');
    }
  });
});

app.post('/check', function(req, res) {
  User.findOne({id: req.body.id}, function(err, docs){
    if(docs !== null && docs.passwd === req.body.pw) {
      req.session.userid = req.body.id;
      req.session.views = 1;
      res.redirect('/');
    } else {
      res.render('login', {
        title: 'login',
        message: 'login form',
        error_message: 'password faild'
      });
    }
  });
});

このままだとログインしっぱなしなので、ログアウト機能も付けましょう。

app.get('/logout', function(req, res) {
  auth.destroy(req.session.id, function(err) {
    req.session.destroy();
    console.log('deleted sesstion');
    res.redirect('/');
  });
});

全ソースはこちら

OpenSSHを使ってrsaでログイン認証の設定

OpenSSHで公開鍵暗号を使ってのログイン認証について軽く調べた。

まず作業の中で登場するものとして、

  1. id_rsa (秘密鍵)
  2. id_rsa.pub (公開鍵)
  3. authorized_keys

の3つがあります。

公開鍵暗号方式についてはこのページがわかりやすいのですが。

公開鍵によって暗号化された情報は、秘密鍵を持つ人にしか解読することができません。なので情報を知りたいAさんは、自分のローカルに秘密鍵と公開鍵を用意し、情報を送るBさんに公開鍵を配ります。BさんはAさんの公開鍵を使って情報を暗号化、送信します。Aさんは自分の秘密鍵を使って情報を解読することができます。

これを認証に利用したのが公開鍵暗号方式の認証です。この方法でBさんから何らかの情報を送りつけて、中身を見る事ができたらAさんだと確認することができます。情報を受けたAさんは、「これで合ってますよね?」とBさんに中身を送り返すことで、Bさんは相手が間違いなくAさんだとわかります。

ログイン認証の場合では、Aさんがクライアント側、Bさんがリモートサーバになります。クライアント側でしなくてはいけないのが、秘密鍵と公開鍵の準備、リモートサーバへ公開鍵を配ることです。一方、リモートサーバではクライアントを確かめるために公開鍵を保存しておかなくてはいけません。そこで公開鍵を保存する場所として出てくるのが、authorized_keysファイルです。

では順番にやってみます。ここはローカルマシンでの作業です。

$ cd .ssh     //.sshディレクトリが無い場合は作ってください
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/username/.ssh/id_rsa):    //無指定でデフォルト名のid_rsaを生成
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/username/.ssh/id_rsa.
Your public key has been saved in /home/username/.ssh/id_rsa.pub.
The key fingerprint is:
...

これで、ローカルに秘密鍵と公開鍵が生成されました。*1 *2
公開鍵の中身をリモートサーバのauthorized_keysに保存します 。

$ scp id_rsa.pub username@xxx.xxx.xxx.xxx:~/.ssh/

リモートにログイン。

$ cd .ssh
$ cat id_rsa.pub >> authorized_keys

ここまでで、秘密鍵、公開鍵、authorized_keysの準備はできました。
これで、リモートサーバ側のsshdを再起動します。

$ /etc/init.d/sshd restart

これで設定は終わりなので、クライアント側に戻ってログインを試してみます。*3

$ ssh username@xxx.xxx.xxx.xxx
Enter passphrase for key '/Users/username/.ssh/id_rsa': 
Last login: Sun Jul  3 01:10:03 2011 from xxx.xxx.xxx.xxx
$

ログインできました。以上で、rsaによるログイン認証は完了です。

*1:OpenSSHでは、ログインの際に.ssh配下のデフォルト名の鍵を読みにいくようです。

*2:-tオプションで暗号化の形式を選択できます。rsaはSSHv2のrsa方式、dsaはSSHv2のdsa方式、rsa1はSSHv1のrsa方式。

*3:場合によっては、"Permission denied (publickey,gssapi-with-mic)."と言われることがある。その場合は、リモート側の.sshディレクトリ、authorized_keysファイルのパーミッションを見直す。[http://d.hatena.ne.jp/h-yano/20080225/1203952174:title=参考]

httpd-2.2.17のconfigureでエラーが出たとこ

環境: sakura vps [ CentOS release 5.5 (Final) ]

configure の指定内容。

./configure --prefix=/usr/local/httpd \
--enable-proxy=shared \
--enable-proxy_ajp=shared \
--enable-ssl=shared \
--enable-mods-shared=all
configure: error: mod_deflate has been requested but can not be built due to prerequisite failures

というエラーが出た。
yum install zlib-devel を実行して、インストールで解決。

configure: error: ...No recognized SSL/TLS toolkit detected

というエラーが出た。
yum install openssl-devel を実行して、インストールで解決。

Scalaでなんちゃって3D[改]

package net.knserve.scala.polygon {
  import java.awt.{ List => _, _ }
  import java.awt.event._

  object Main {
    def main( args: Array[ String ] ): Unit = {
      val p0 = Point3( -100,  100, -100, 1 )
      val p1 = Point3(  100,  100, -100, 1 )
      val p2 = Point3(  100, -100, -100, 1 )
      val p3 = Point3( -100, -100, -100, 1 )
      val p4 = Point3( -100,  100,  100, 1 )
      val p5 = Point3(  100,  100,  100, 1 )
      val p6 = Point3(  100, -100,  100, 1 )
      val p7 = Point3( -100, -100,  100, 1 )
      val cubic = Cubic(
        Face( p0, p1, p2, p3 ),
        Face( p4, p5, p6, p7 ),
        Face( p0, p4, p5, p1 ),
        Face( p1, p5, p6, p2 ),
        Face( p2, p6, p7, p3 ),
        Face( p3, p7, p4, p0 )
      )
      val drw = new Draw( cubic )
      drw.setBackground( Color.black )
      drw.setSize( 400, 400 )
      drw.setVisible( true )
      val thr = new Thread( drw )
      thr.start
    }
  }

  case class Point3( x: Double, y: Double, z: Double, s: Double ) {

    type Matrix[T] = List[ List[T] ]
    type Rotation[T] = List[ T ]

    def determinantZ( r: Rotation[ Double ] ): Matrix[ Double ] = List(
      List( cos(r(2)), sin(r(2)), 0, 0 ),
      List( -sin(r(2)), cos(r(2)), 0, 0 ),
      List( 0, 0, 1, 0 ),
      List( 0, 0, 0, 1 )
    ) 

    def determinantY( r: Rotation[ Double ] ): Matrix[ Double ] = List(
      List( cos(r(1)), 0, -sin(r(1)), 0 ),
      List( 0, 1, 0, 0 ),
      List( sin(r(1)), 0, cos(r(1)), 0 ),
      List( 0, 0, 0, 1 )
    )

    def determinantX( r: Rotation[ Double ] ): Matrix[ Double ] = List(
      List( 1, 0, 0, 0 ),
      List( 0, cos(r(0)), sin(r(0)), 0 ),
      List( 0, -sin(r(0)), cos(r(0)), 0 ),
      List( 0, 0, 0, 1 )
    )

    def sin( d: Double ) = math.sin( math.toRadians( d ))
    def cos( d: Double ) = math.cos( math.toRadians( d ))

    def affine( m: Matrix[Double] ): Point3 = {
      def fusion( a: List[Double], b: List[Double], f: (Double, Double) => Double ) =
        a.zip( b ).map( org => f( org._1, org._2 ) )
      Point3( fusion( toList, List.transpose( m )(0), _*_ ).foldLeft(0.0)(_+_),
              fusion( toList, List.transpose( m )(1), _*_ ).foldLeft(0.0)(_+_),
              fusion( toList, List.transpose( m )(2), _*_ ).foldLeft(0.0)(_+_),
              fusion( toList, List.transpose( m )(3), _*_ ).foldLeft(0.0)(_+_)
            )
    }

    def rotate( r: Rotation[ Double ] ) =
      affine( determinantX( r ) ).
        affine( determinantY( r ) ).
          affine( determinantZ( r ) ) 

    def toList = List( x, y, z, s )
  }
  
  case class Face( points: Point3* ) {
    def toList: List[ Point3 ] = points.toList
  }
  
  case class Cubic( faces: Face* ) {
    def toList: List[ Face ] = faces.toList
  }

  object World {
    val axis3Depth = 400
    val screenDepth = 320
  }

  object Draw {
    val axis2X = 200
    val axis2Y = 200
    val convert2d: ( Double, Double, Double ) => Int =
      ( x1, L1, L2 ) => (( x1 * L2 ) / L1).toInt
    def P3toP2( p: Point3 ): Tuple2[Int, Int] = (
      convert2d( p.x, World.axis3Depth+p.z, World.screenDepth ),
      convert2d( p.y, World.axis3Depth+p.z, World.screenDepth )
    )

    def polygonFactory( fc: List[Point3] ): Polygon = {
      val plist = fc.map( p => P3toP2( p ) )
      new Polygon(
        plist.map( p => p._1 + axis2X ).toArray,
        plist.map( p => p._2 + axis2Y ).toArray,
        plist.length
      )
    }
  }

  class Draw( cubic: Cubic ) extends Frame with Runnable with MouseMotionListener {
    
    addMouseMotionListener( this )
    addWindowListener( new WindowAdapter {
        override def windowClosing( e: WindowEvent ): Unit = {
          System.exit( 0 )
        }
    })

    val c: Cubic = cubic
    var r: List[Double] = List( 0.0, 0.0, 0.0 )

    override def paint( g: Graphics ): Unit = {
      g.setColor( Color.white )
      val rotated = c.toList.map( fc => fc.toList.map( p => p.rotate( r ) ) )
      rotated.foreach( fc => g.drawPolygon( Draw.polygonFactory( fc ) ) )
    }

    def mouseMoved( e: MouseEvent ): Unit = {
      r = List( e.getY-Draw.axis2Y, -( e.getX-Draw.axis2X ), 0.0 )
    }

    def mouseDragged( e: MouseEvent ): Unit = {
    }

    def run(): Unit = {
        try {
            while( true ) {
                repaint
                Thread.sleep( 30 )
            }
        } catch {
            case e: InterruptedException =>
                println( e.getMessage )
            }
        }
  }
}