Security Check List

系統剛安裝完成時,安全性相對是最不足的,尤其是現在 VPS 盛行,每個人都可以輕鬆開啟屬於自己的 VPS ,因此 Security Check List 絕對是不能少的

Linux

  1. 建立 root 以外的 sudoer 帳號

    新增使用者

    adduser <username>
    

    將使用者設定為 sudoer

    sudo visudo
    

    在 #User privilege specification 下方新增使用者

    <username>    ALL=(ALL:ALL) ALL
    

    最後別忘了進行reboot讓設定生效

    reboot
    
  2. 產生 SSH Key 並改用 SSH Key 登入

    使用 ssh-keygen 產生 key-pair

    ssh-keygen -t rsa        
    

    畫面上會出現以下指令,可以直接 enter ,將 key 存在預設位置

    Enter file in which to save the key (/home/<username>/.ssh/id_rsa):
    

    接著決定 key 的密碼

    Enter passphrase (empty for no passphrase):
    

    執行的畫面大致如下

    ssh-keygen -t rsa
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/<username>/.ssh/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:
    4a:dd:0a:c6:35:4e:3f:ed:27:38:8c:74:44:4d:93:67 <username>@a
    The key's randomart image is:
    +--[ RSA 2048]----+
    |          .oo.   |
    |         .  o.E  |
    |        + .  o   |
    |     . = = .     |
    |      = S = .    |
    |     o + = +     |
    |      . o + o .  |
    |           . o   |
    |                 |
    +-----------------+
    

    最後將 /home/<username>/.ssh/id_rsa.pub 下載回來複製到本機的 /home/<username>/.ssh/authorized_keys 資料夾下

    下次就可以改用 SSH key 登入,不用輸入密碼了

  1. 關閉 Root Login / Password Login

    開啟 sshd 設定檔

    sudo vi /etc/ssh/sshd_config
    

    設定以下欄位

    # 關閉 root 登入功能
    PermitRootLogin no
    # 關閉密碼登入功能
    # 要記得先確定可以使用SSH Key登入或可以直接操作本機
    PasswordAuthentication no
    

    重新啟動服務,讓設定生效

    sudo service ssh restart
    
  2. 定期更新系統

    編寫自動更新的 script

    sudo vi /etc/cron.daily/auto-upgrade
    

    寫入以下內容

    #!/bin/sh
    apt-get update
    apt-get -y dist-upgrade
    apt-get clean
    

    並修改權限為 755,(或把 owner 改為 root 也行)

    sudo chmod 755 /etc/cron.daily/auto-upgrade
    

    重新啟動 cron 服務

    sudo /etc/init.d/cron restart
    
  3. 建立防火牆規則

防火牆下次再補…

PHP - Server-Side Parser - Simple HTML DOM Parser

在Client Side,可以直接利用各種不同的Library,例如javascript或著jquery所提供的Selector進行DOM的尋訪,可以快速地找到DOM的內容進行查詢甚至處理。

Server Side同樣也有類似的Library,如 phpQueryQueryPath 等,及PHP Simple HTML DOM Parser

這邊強烈建議千萬要使用 PHP Simple HTML DOM Parser 來進行開發,相較於 phpQueryQueryPath 的文件相對豐富,但整體資源最豐富及簡單使用的,還是 PHP Simple HTML DOM Parser

PHP Simple HTML DOM Parser,不只支援 CSS Selector,也支援 XPath Selector。

Example 1:

// Create DOM from URL
$html = file_get_html('http://www.google.com/');

// Find all images
foreach($html->find('img') as $element)
   echo $element->src . '<br>';

// Find all links
foreach($html->find('a') as $element)
   echo $element->href . '<br>';

Example 2:

// Create DOM from String
$html = str_get_html('<html><body>Hello!</body></html>');

// XPath Selector
echo $html->find('/html/body')->innertext;

Example 3:

// Create DOM from string
$html = str_get_html('<div id="hello">Hello</div><div id="world">World</div>');

$html->find('div', 1)->class = 'bar';

$html->find('div[id=hello]', 0)->innertext = 'foo';

echo $html; // Output: <div id="hello">foo</div><div id="world" class="bar">World</div>

Written with StackEdit.

PHP - Custom $_SERVER Variable

CodeIngiter ( CI ) 內建有環境設定的功能,預設有 “development”, “production”, “testing” 等 pre-define 的環境可供選擇。切換環境的同時,也會切換不同組的 config ,如此一來開發者可以更簡單的管理各種環境。這和 Custom $_SERVER Variable ( 自訂 $_SERVER 變數 ) 又有什麼關係呢 ? 主要就是 CI 在根目錄下的 index.php 寫了這些代碼來做環境判斷

define('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development');

也就是我們可以根據 $_SERVER[‘CI_ENV’] 內的值來決定目前是哪種環境。

$_SERVER 無法修改?

但像這種 $_SERVER 變數我們是無法隨意寫入的,若想瞭解可以增加以下 Controller 進行測試,依序執行 test1() 、 test2() 就可以發現,在 test1() 中設定好的 CI_ENV 在 test2() 就看不到了。

<?php
    defined('BASEPATH') OR exit('No direct script access allowed');

    class Test_server_var extends CI_Controller {

        public function test1()
        {
            print('----test1----<br>');
            $_SERVER['CI_ENV'] = 'production';
            print_r($_SERVER);
        }

        public function test2()
        {
            print('----test2----<br>');
            print_r($_SERVER);
        }
}

設定 $_SERVER[‘CI_ENV’]

設定方法其實很簡單,可以分為兩步驟

Step 1 - 確認 mod_env 是否已經 enable

直接檢查 /etc/apache2/mods-enabled 內是否有 env.load ,若有則表示已經啟動,若沒有則可以輸入以下指令啟動

# 啟動模組
sudo a2enmod env
# 重啟服務
sudo service apache2 restart

Step 2 - 在網站設定檔內加上 SetEnv

開啟 /etc/apache/sites-available/000-default.conf ( 預設 ),加上 SetEnv

ServerName emoticon.cc
ServerAdmin allanfann@gmail.com
DocumentRoot /var/www/emoticon.cc/public_html
<font color="red">SetEnv CI_ENV production</font>

Step 3 - 測試

直接執行先前的 test2(),應該就可以直接看到 “CI_ENV” => “production” 的內容了

Reference

Slack - 聊天機器人

Slack 算是近年來異軍突起的 IM (Instant Message) 軟體,除了主打工作用的即時通訊外,其他如:文件管理、私人頻道之類的設計,對我來說,光是聊天室內檔案不會被刪除,並且會可以檢索的到,這功能就方便太多了。

Slack 對於開發者還有提供對話機器人的功能,透過這樣機器人串接其他的 Web Application 可以完成不少的自動化功能,尤其對於開發者在自動化某些工作時,更是方便。

在這次範例,非常單純,只是要從 Heroku 的 Server 上送出 Hello 而已

  1. 建立 local repo,直接利用 github 上的 template 來建立

     git clone https://github.com/heroku/node-js-getting-started.git slackbot
    cd slackbot
    
  2. 在 heroku 上面建立 app,並且將現有的 template push 上去

    heroku create
    git remote add heroku master
    git push heroku master
    
  3. 去自己的 slack team 的 url 搜尋 SlackBot 並且進行安裝

    https://<your_team>.slack.com/apps
    
  4. 參考 SlackBot example url

    安裝完成後,點擊進入 Edit Configuration 可以看到類似這樣的 example

    curl --data "Hello from Slackbot" $'https://<your_team>.slack.com/services/hooks/slackbot?token=<token>&channel=%23general'
    

    利用 curl 進行呼叫,就可以在 Slack 上收到 Hello from Slackbot

  5. 寫入到 index.js

    var request = require('request');
    
    var url = "https://<your_team>.slack.com/services/hooks/slackbot";
    var token = "<your_token>";
    var channel = "<your_channel>";
    
    function slack_send_message(msg) {
    
      var slack_url = url;
      slack_url += "?token=" + token;
      slack_url += "&channel=%23" + channel;
    
      request.post(
        {
          url: slack_url,
          body: msg,
          encoding:'utf8'
        },
        function(error, response, body){
          console.log(response.statusCode);
        }
      );
    }
    
  6. 測試及佈署

    // 本地測試
    nodejs index.js
    
    // 佈署及遠端測試
    git push heroku master
    heroku open
    
  7. 結論

    這篇只是單純的 Hello World 而已 ,有機會在分享相關的應用

SlackBot 補充說明:

  1. 要將訊息送到哪個頻道必須標示出來
  2. 要傳出的文字內容必須使用 Http Post 將來進行傳送
  3. 內容中如果有網址或著@提到某人時,會自動連結
  4. 每秒只可以送出一筆訊息

Linux - 新增使用者帳號

新增使用者帳號雖然不至於說經常使用,但也算是基本指令之一了,唉唉、偏偏老是記不起來,還是寫起來最實在

新增使用者

    adduser <username>

將使用者設定為sudoer

    sudo visudo

在`#User privilege specification`在`root`下方新增使用者

    <username>    ALL=(ALL:ALL) ALL

最後別忘了進行reboot讓設定生效

    reboot

Reference

Linux Security - fail2ban

Linux的遠端登入對於使用者來說,最怕的還是被 bot 用暴力破解法慢慢地try出密碼。此時我們可以提出的對應方法不外乎 1) 改用 RSA Key 登入(可參考 Security Check List - Linux、2) 使用強密碼,3) 對連續登入錯誤增加處理機制,本篇所提的 fail2ban 就是屬於第三類型的處理。

Install

安裝很簡單,執行個命令而已

sudo apt-get install fail2ban

設定 fail2ban

  1. 自範本複製設定檔

    sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

  2. 修改 ssh section下的設定

    [ssh]  #開頭名稱可以自定
    enabled  = true
    port     = ssh
    filter   = sshd
    logpath  = /var/log/auth.log
    maxretry = 6
    # 若連續try了6次,則永久封鎖
    bantime=-1 
    
  3. 重啟服務

    sudo service fail2ban restart
    

fail2ban 設定簡介

sudo vi /etc/fail2ban/jail.conf
fail2ban的設定檔位置在 /etc/fail2ban目錄下,有以下幾個設定檔:

  1. jail.conf
    主要設定檔的範本,使用時應先複製此檔案並重新命名為jail.local,設定檔內分全域設定(DEFAULT)及個別設定(eq: ssh, apache),有個別設定時,以個別設定為主。

  2. fail2ban.conf
    fail2ban的設定檔,設定loglevel、logtarget、socket、pidfile等資訊

  3. filter.d/
    存放 fail2ban 過濾條件設定檔

  4. action.d/
    存放 fail2ban 阻擋動作設定檔

參考

MySQL - Table is marked as crashed and should be repaied


今天例行檢查網站是否正常運作時,突然發現網站居然掛掉了,嚇得我一身冷汗,除了立即通知相關人士外,立馬查了一下是哪邊的問題。猛然發現 MySQL 的服務居然停了..,賣鬧阿!!

查詢Log 看到一大串這樣的文字

[ERROR] Table './xxx/xxx' is marked as crashed and should be repaired
[ERROR] Table './xxx/xxx' is marked as crashed and should be repaired
[ERROR] Table './xxx/xxx' is marked as crashed and should be repaired
[ERROR] Table './xxx/xxx' is marked as crashed and should be repaired

似乎好幾個表格都壞掉了,修正的方法還算蠻簡單的,只要利用 mysqlcheck 就可以修復

mysqlcheck -u <user> -p <dbname> --auto-repair

雖然這次很幸運救回來了,但不論如何,DB都應該定期備份,一旦資料丟失真的後果不堪設想..

PHP - 取得系統時間

利用 date()函數就可以取得系統時間

<?php
    echo date("Y-m-d H:i:s");
?>
Format Char Description Example
Y 西元年四碼 2015
m 月份兩碼,有補0 05
d 日期兩碼,有補0 04
H 時,24小時制 14
i 分,有補0 03
s 秒,有補0 28

參考:

  1. date(), PHP

PHP - 變更時區

在未設定時區之前,若直接透過date()去取得的時間會是國際標準時間,
以台北時間來說就等於少了八小時。

  1. 開啟php.ini

    sudo nano /etc/php5/apache2/php.ini
    
  2. 修改time zone

    [Date]
    ; Defines the default timezone used by the date functions
    ;date.timezone = 
    date.timezone = Asia/Taipei
    
  3. 重新啟動apache

    sudo service apache2 restart
    

MySQL - 常用設定

不管是在做網站開發或著資料庫程式開發, MySQL 每次總有固定的起手式…,建立資料庫 / 建立使用者 / 設定權限等屢試不爽。這次來記錄一下這個部分,方便以後的查詢。

以 MySQL 為例

  1. 進入CLI

    msql -uroot -p
    
  2. 建立資料庫

    # create database <database_name>
    create  database my_database;
    
  3. 建立使用者

    # create user '<username>'@'<host>' identified by '<password>';
    # <host>用來指定來源主機位址
    # 基於安全考量,密碼不要用得太簡單
    create user 'cwfan'@'localhost' identified by 'my_password';
    # 由於mysql的命令會被存入 ~/.mysql_history 
    # 可透過 PASSWORD() 避免將密碼明碼寫入
    create user 'cwfan'@'localhost' identified by password  '*90E462C37378CED12064BB3388827D2BA3A9B689';
    
  4. 設定權限

    # grant <option> on <target> to <user>;
    
    # 給予 cwfan 對於 my_database 全部表格的所有權限
    grant all on my_database.* to 'cwfan'@'localhost';
    
    # 給予 cwfan 所有資料庫的所有權限
    # 教學常看到,但應該避免這樣給定權限
    grant all on *.* to 'cwfan'@'localhost';
    # 僅給予 cwfan 查詢的權限
    grant select on my_database.* to 'cwfan'@'localhost';
    
  5. 刪除使用者

    # drop user '<username>'@'<host>';
    drop user 'cwfan'@'localhost';
    
  6. 刪除資料庫

    # drop database <database_name>
    drop database my_database;
    

參考