Cloud9へのPHP7とLaravelの導入

Cloud9のワークスペース作成画面でLaravelの入ったGitプロジェクトを入力してワークスペースの作成が終わったところから開始するとして、以下C9上で入力していきます。

PHP7と必要パッケージの導入

PHP5とphpmyadminを削除(使う人は残してください)。

masasikatano:~/workspace (master) $ sudo apt-get purge -y php5-common
masasikatano:~/workspace (master) $ sudo apt-get purge phpmyadmin
masasikatano:~/workspace (master) $ sudo apt-get autoremove

PHP7とLaravelに必要なパッケージをインストールしてcomposer installします

masasikatano:~/workspace (master) $ sudo add-apt-repository ppa:ondrej/php
masasikatano:~/workspace (master) $ sudo add-apt-update
masasikatano:~/workspace (master) $ sudo add-apt-upgrade
masasikatano:~/workspace (master) $ sudo apt-get install php7.0 libapache2-mod-php7.0 php7.0-mbstring  php7.0-zip php7.0-xml php7.0-mysql php7.0-fpm php7.0-curl
masasikatano:~/workspace (master) $ composer install
masasikatano:~/workspace (master) $ composer update

Apache関連の設定変更

まずはDocument Rootをpubclic以下へ変更

masasikatano:~/workspace (master) $ sudo vi /etc/apache2/sites-available/001-cloud9.conf
<VirtualHost *:8080>
    DocumentRoot /home/ubuntu/workspace/public
    ServerName https://${C9_HOSTNAME}:443

    LogLevel info

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Directory /home/ubuntu/workspace>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

ディレクトリのパーミッションを変更

masasikatano:~/workspace (master) $chmod 777 -R bootstrap/cache
masasikatano:~/workspace (master) $chmod 777 -R storage

MySQLのrootユーザのパスワード変更

masasikatano:~/workspace (master) $ mysql -u root
mysql> update mysql.user set password=password('password1234') where user = 'root';
mysql> flush privileges;

 

とりあえずこれで動くと思います。

TCPサーバを立ててみる

UNIXネットワークプログラミング入門という本を読んで、恥ずかしながらC言語でかんたんにTCPのサーバが立てられるということを知りました。さっそくCloud9で実装してみたいと思います。

テキストはWEBでも見ることができます雪田教授に感謝です。

Cloud9でC++のWorkspaceを作成して、以下のファイル群を作っていきます。

/home/ubuntu/workspace/one2one.h
/*********************************************/
/* File name: one2one.h */
/* Project name: socket/1-1 */
/* Month/Year: Jan/2003 */
/* Author: Shuichi YUKITA */
/*********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 50000
#define HOSTNAME_LENGTH 20
#define MSG_BUF_LEN 512

extern char * chop_newline(char *, int);

 

/home/ubuntu/workspace/server.c
/*********************************************/
/*       File name:  server.c                */
/*    Project name:  socket/1-1              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "one2one.h"

main()
{
  struct  sockaddr_in   me;
  int  s,snew;
  char  send_buf[MSG_BUF_LEN];
  char  recv_buf[MSG_BUF_LEN];
  int count;

  memset((char *)&me, 0, sizeof(me));
  me.sin_family = AF_INET;
  me.sin_addr.s_addr = htonl(INADDR_ANY);
  me.sin_port = htons(PORT);

  if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0 )	{
    perror("socket");
    exit(1);
  }

  if (bind(s,(struct sockaddr *)&me,sizeof(me)) == -1){
    perror("bind");
    exit(1);
  }

  listen(s,1);
  fprintf(stderr,"successfully bound, now waiting.\n");
  snew = accept(s,NULL,NULL);
  close(s);

  do	{
    printf("input: ");
    fgets(send_buf,MSG_BUF_LEN,stdin);
    /*    chop_newline(send_buf,MSG_BUF_LEN);*/
    write(snew,send_buf,strlen(send_buf));
    count = read(snew,recv_buf,MSG_BUF_LEN);
    recv_buf[count] = '\0';
    printf("client: %s",recv_buf);
  }
  while (strncmp(recv_buf,"quit",4) != 0);

  close(snew);
}

 

/home/ubuntu/workspace/client.c
/*********************************************/
/*       File name:  client.c                */
/*    Project name:  socket/1-1              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "one2one.h"

main()
{
  struct  hostent  *server_ent;
  struct  sockaddr_in  server;
  int s;  /* descriptor for socket */
  char  send_buf[MSG_BUF_LEN];
  char  recv_buf[MSG_BUF_LEN];
  char  hostname[HOSTNAME_LENGTH];
  int   count;

  printf("input  server's  hostname: ");
  fgets(hostname, HOSTNAME_LENGTH, stdin);
  chop_newline(hostname, HOSTNAME_LENGTH);

  if((server_ent = gethostbyname(hostname)) == NULL){
    perror("gethostbyname");
    exit(1);
  }

  memset((char *)&server,0,sizeof(server));
  server.sin_family = AF_INET;
  server.sin_port = htons(PORT);
  memcpy((char *)&server.sin_addr, server_ent->h_addr, 
   server_ent->h_length);

  if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0){
    perror("socket");
    exit(1);
  }

  if (connect(s,(struct sockaddr *)&server,sizeof(server)) == -1){
    perror("connect");
    exit(1);
  }
  fprintf(stderr,"connected.\n");

  do   {
    count = read(s,recv_buf,MSG_BUF_LEN);
    recv_buf[count] = '\0';
    printf("server: %s",recv_buf);
    printf("input: ");
    fgets(send_buf,MSG_BUF_LEN,stdin);
    /*    chop_newline(send_buf,MSG_BUF_LEN);*/
    write(s,send_buf,strlen(send_buf));
  }
  while( strncmp(send_buf,"quit",4) != 0 );

  close(s);
}

 

/home/ubuntu/workspace/chop_newline.c
/*********************************************/
/*       File name:  chop_newline.c          */
/*    Project name:  socket/1-1              */
/*      Month/Year:  Jan/2003                */
/*          Author:  Shuichi YUKITA          */
/*********************************************/

#include "one2one.h"

char * chop_newline(char *str, int len){
  int n = strlen(str);

  if(n < len && str[n-1] == '\n'){
    str[n-1] = '\0';
  }
  return str;
}

 

/home/ubuntu/workspace/Makefile
#*********************************************/
#*       File name:  Makefile                */
#*    Project name:  socket/1-1              */
#*      Month/Year:  Jan/2003                */
#*          Author:  Shuichi YUKITA          */
#*********************************************/
#
#  "root.o" target is implicitly built by
#  $(COMPILE.c) -o root.o root.c

RM=rm -f

all:	s c

s:	server.o chop_newline.o
  $(LINK.c)  -o s  server.o chop_newline.o

c:	client.o chop_newline.o
  $(LINK.c)  -o c  client.o chop_newline.o

server.o:	server.c one2one.h

client.o:	client.c one2one.h

clean:
  $(RM) s c *.o *~

 
ここまでヘッダファイル1つ、サーバ用ファイル1つ、クライアント用ファイル1つ、計5つのファイルを作成したらmakeをします。

masasikatano:~/workspace $ make
cc    -c -o chop_newline.o chop_newline.c
cc      -o s  server.o chop_newline.o
cc    -c -o client.o client.c
cc      -o c  client.o chop_newline.o

コンパイルが完了したら、サーバとクライアントを起動することができます。まずはサーバを起動します。

masasikatano:~/workspace $ ./s
successfully bound, now waiting.

同じCloud9上で別のターミナルを立ち上げてクライアントを立ち上げてみます。

masasikatano:~/workspace $ ./c
input  server's  hostname: localhost
connected.

こうするとサーバ側でinputの表示がされ、文字入力を受付ける状態になり、文字を入力するとクライアント側で表示されます。すげえ。

Raspberry Pi のサーバ最適化とセキュリティ設定まとめ

いままでRaspberryPiにいろいろなセキュリティを行ってきたのですが新ブログに移転したのもあるので内容をまとめておきます。セキュリティには4つの重要な要素があります。

制限する

一番安全で強力なセキュリティの方法はネットワークに接続しないことです。(後に紹介する)冗長化や監視に必要なアプリケーションは残しておきますが、可能な限りのアプリケーションは停止します。

参考: Raspberry Pi 起動高速化手順メモ

ラズパイへの施行例

root@rpi1 /var/www #chkconfig --list
alsa-utils                0:off  1:off  2:off  3:off  4:off  5:off  6:off
apache2                   0:off  1:off  2:on   3:on   4:on   5:on   6:off
atd                       0:off  1:off  2:on   3:on   4:on   5:on   6:off
avahi-daemon              0:off  1:off  2:off  3:off  4:off  5:off  6:off
bluetooth                 0:off  1:off  2:off  3:off  4:off  5:off  6:off
bootlogs                  0:off  1:on   2:on   3:on   4:on   5:on   6:off
bootmisc.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
checkfs.sh                0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
checkroot-bootclean.sh    0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
checkroot.sh              0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
console-setup             0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
cron                      0:off  1:off  2:on   3:on   4:on   5:on   6:off
dbus                      0:off  1:off  2:off  3:off  4:off  5:off  6:off
dhcpcd                    0:off  1:off  2:on   3:on   4:on   5:on   6:off
dphys-swapfile            0:off  1:off  2:off  3:off  4:off  5:off  6:off
dropbear                  0:off  1:off  2:on   3:on   4:on   5:on   6:off
fake-hwclock              0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
hostname.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
hwclock.sh                0:off  1:off  2:off  3:off  4:off  5:off  6:off
kbd                       0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
keyboard-setup            0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
killprocs                 0:off  1:on   2:off  3:off  4:off  5:off  6:off
kmod                      0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
motd                      0:off  1:off  2:off  3:off  4:off  5:off  6:off
mountall-bootclean.sh     0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountall.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountdevsubfs.sh          0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountkernfs.sh            0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountnfs-bootclean.sh     0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mountnfs.sh               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
mysql                     0:off  1:off  2:off  3:off  4:off  5:off  6:off
networking                0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
nfs-common                0:off  1:off  2:off  3:off  4:off  5:off  6:off
ntp                       0:off  1:off  2:on   3:on   4:on   5:on   6:off
php7.0-fpm                0:off  1:off  2:on   3:on   4:on   5:on   6:off
plymouth                  0:off  1:off  2:off  3:off  4:off  5:off  6:off
plymouth-log              0:off  1:off  2:off  3:off  4:off  5:off  6:off
procps                    0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
raspi-config              0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
rc.local                  0:off  1:off  2:on   3:on   4:on   5:on   6:off
rcS                       0:off  1:off  2:off  3:off  4:off  5:off  6:off
rmnologin                 0:off  1:off  2:on   3:on   4:on   5:on   6:off
rpcbind                   0:off  1:off  2:off  3:off  4:off  5:off  6:off
rsync                     0:off  1:off  2:on   3:on   4:on   5:on   6:off
rsyslog                   0:off  1:off  2:on   3:on   4:on   5:on   6:off
sendsigs                  0:off  1:off  2:off  3:off  4:off  5:off  6:off
sudo                      0:off  1:off  2:off  3:off  4:off  5:off  6:off
triggerhappy              0:off  1:off  2:off  3:off  4:off  5:off  6:off
udev                      0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
udev-finish               0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on
umountfs                  0:off  1:off  2:off  3:off  4:off  5:off  6:off
umountnfs.sh              0:off  1:off  2:off  3:off  4:off  5:off  6:off
umountroot                0:off  1:off  2:off  3:off  4:off  5:off  6:off
urandom                   0:off  1:off  2:off  3:off  4:off  5:off  6:off  S:on

また、PHPの便利すぎてクラッキングにも使えるfunctionを制限しておきます。

参考: Dangerous PHP Functions Must be Disabled

ラズパイへの施行例 (php.iniファイルを編集して、Apache再起動すると反映されます。)

root@rpi1 /etc/php/7.0/apache2 #less php.ini
; 中略
; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names.
; http://php.net/disable-functions
disable_functions = phpinfo,system,popen,show_source,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

冗長化する

セキュリティには可用性も重要です。二番目は可用性を確保するために可能な限りスペアのアプリケーションを用意しておき、どこかに異常が現れた際にすぐに代用が可能な状態にすることです。

参考 : Raspberry Pi チューニング – DBサーバの独立と移行

監視する

問題を事前に発見するために監視を怠らないようにするのもセキュリティにはとても重要です。
サーバのメトリクス(評価尺度)を可視化するのは、Mackerelがかんたんに導入できておすすめです。ロードアベレージが一定数を超えたらメールが飛んでくるように設定することもできます。

参考 : Raspberry Pi を Mackerel で監視する

空にする

最後に意図して情報資産を保持しないようにするのも効果的な方法です。お金を自宅に置かずに銀行に預けるように、お金に関わる情報や個人情報等の情報資産は外部サイトにあずけてしまうのも手です。