Laravel Horizon

Info

Installation

composer require laravel/horizon
  • 產生 UI 介面檔案
php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"

Setting

  • 所有設定都在 config/horizon.php
config/horizon.php
return [
    // 使用連線名稱,對應 config/database.php Redis 的連線設定值,建議用一個獨立的連線設定 e.g. horizon
    'use' => 'horizon',
 
    // 在 Redis 中的前置詞,使用預設
    'prefix' => env('HORIZON_PREFIX', 'horizon:'),
 
    // 程式執行過久的時間設定(單位:秒),似乎與通知有關;沒有用到,使用預設
    'waits' => [
        'redis:default' => 60,
    ],
 
    // 在 Laravel Horizon 介面中 "Recent Jobs" 與 "Failed" 資料存活時間(單位:分),使用預設
    'trim' => [
        'recent' => 60,
        'failed' => 10080,
    ],
 
    // 重要環境設定
    'environments' => [
        // production 環境
        'production' => [
            // 相當於之前在 supervisor 中的設定
            'supervisor-test' => [
                // queue 連線使用 redis,,對應 config/queue.php Redis 的設定值,使用預設
                'connection' => 'redis',
                // queue 名稱列表,如果沒有使用 balance 會依照順序執行:queue1 > queue2 > queue3
                'queue' => ['queue1', 'queue2', 'queue3'],
                // 平衡設定:false(不使用), 'simple'(平均), 'auto'(自動調整,會給比較忙的 queue 多一點 worker)
                'balance' => false,
                // worker 數
                'processes' => 1,
                // 重試次數
                'tries' => 3,
            ],
 
            'supervisor-balance' => [
                'connection' => 'redis',
                // queue4 = queue5, worker 數自動分配
                'queue' => ['queue4', 'queue5'],
                // 自動調整
                'balance' => 'auto',
                'processes' => 10,
                'tries' => 3,
            ],
        ],
 
        // local 本機環境
        'local' => [
            'supervisor-test' => [
                'connection' => 'redis',
                'queue' => ['queue1', 'queue2', 'queue3'],
                'balance' => false,
                'processes' => 1,
                'tries' => 3,
            ],
 
            'supervisor-balance' => [
                'connection' => 'redis',
                'queue' => ['queue4', 'queue5'],
                'balance' => 'auto',
                'processes' => 10,
                'tries' => 3,
            ],
        ],
    ],
];

Usage

  • 改用 Horizon 管理 queue
php artisan horizon
  • 修改 Supervisor 設定
sudo vi /etc/supervisor/conf.d/laravel-worker.conf
/etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-horizon]
process_name=%(program_name)s
command=php /var/www/project/artisan horizon
autostart=true
autorestart=true
user=root
redirect_stderr=true
stdout_logfile=/var/www/project/storage/logs/horizon.log
  • 重讀 Supervisor 設定
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-horizon:*
  • 可以在 /app/Providers/AppServiceProvider.php 另外加入驗證,讓特定環境/IP/使用者才能看到監控介面
public function boot()
{
    // ...
 
    // horizon authentication
    Horizon::auth(function(Request $request) {
        return ($this->app->environment('local') || in_array($request->ip(), ['xxx.xxx.xxx.xxx']) || auth()->guard('admin')->check());
    });
}

Deploying

  • 因為現在改由 Horizon 管理 queue,之前使用的
    php artisan queue:restart

    要修改成

    php artisan horizon:terminate
  • 其他設定上的修改可以參考Deploying Horizon To Laravel Forge

Trouble Shooting

Monitor Tag 送出沒有反應

  • 因為被 middleware VerifyCsrfToken 擋下來,可以參考這邊的做法忽略
protected $except = [
    // ...
    'horizon/*',
];

Jobs 憑空消失

  • 不確定是不是 bug,但這邊提供設定似乎可以解決,在 config/queue.php Redis 的連線設定中加入參數
'redis' => [
    'driver' => 'redis',
    'connection' => 'queue',
    'queue' => 'default',
    'retry_after' => 90,
    // 加入此設定
    'block_for' => null,
],

MISCONF Redis is configured to save RDB snapshots

Reference

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

vsftpd

Info

Install on AWS EC2

  • 更新套件並安裝 vsftpd
sudo apt-get update
sudo apt-get install vsftpd -y
  • vsftpd 設定
sudo vi /etc/vsftpd.conf
# 關閉 ipv6,這個問題卡很久,找很久才發現解決方式;不確定是不是 vsftpd 版本的問題
# https://www.centos.org/forums/viewtopic.php?t=52408
listen=YES
listen_ipv6=NO
 
# 允許本地用戶登錄
local_enable=YES
 
# 允許上傳
write_enable=YES
 
# 讀寫執行權限
local_umask=022
 
# 允許家目錄變為根目錄
chroot_local_user=YES
chroot_list_enable=YES
 
# 允許家目錄變為根目錄後擁有寫入權限
chroot_list_file=/etc/vsftpd.chroot_list
allow_writeable_chroot=YES
  • 建立使用者 test
sudo useradd -m -s /usr/sbin/nologin test
sudo passwd test
# 之後輸入二次密碼
  • nologin 加入 shells 最後
sudo vi /etc/shells
/usr/sbin/nologin
  • 如果使用者要可以看到所有目錄,新增帳號到這個檔案;如果不需要也要建立一個沒有內容的檔案

sudo vi /etc/vsftpd.chroot_list
  • 重啟 vsftpd
sudo service vsftpd restart

使用 TSL 連線(SSL)

如果沒有憑證可以自簽

  • 利用 openssl 產生憑證檔案
# 產生一個期限為 3650 天的自簽憑證
sudo openssl req -x509 -nodes -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem -days 3650 -newkey rsa:2048
  • 自簽範例參考
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:Los Angeles
Organization Name (eg, company) [Internet Widgits Pty Ltd]:example.com
Organizational Unit Name (eg, section) []:Linux and Open Source
Common Name (e.g. server FQDN or YOUR name) []:example
Email Address []:info@example.com

修改 vsftpd 設定檔

  • 自簽設定
sudo vi /etc/vsftpd.conf
#rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
rsa_cert_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES
ssl_ciphers=HIGH
  • 如果 EC2 上已有憑證
#rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
rsa_cert_file=/etc/letsencrypt/live/example.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/example.com/privkey.pem
ssl_enable=YES
ssl_ciphers=HIGH
  • 重啟 vsftpd
sudo service vsftpd restart

使用被動模式

  • 有興趣可以詳讀 FTP 主/被動模式
  • 我自己的理解是:當 Client 端在 NAT 架構下,使用被動模式比較不容易有問題(如果有錯請再告知)
  • 修改 vsftpd 設定檔
sudo vi /etc/vsftpd.conf
pasv_enable=YES
pasv_min_port=40000
pasv_max_port=50000
port_enable=YES
pasv_address=[Public IP]
 
# 使用 domain name 時
#pasv_address=[Domain Name]
#pasv_addr_resolve=YES<.code>
  • 重啟 vsftpd
sudo service vsftpd restart
  • AWS EC2 Security Group 要開啟被動模式的 port range

5232310_raw.jpg

Reference

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

UltraHook

Info

  • UltraHook makes it super easy to connect public webhook endpoints with development environments
  • support GitHub, Stripe, ActiveCampaign, Papertrail

Usage

gem install ultrahook
  • 寫入 UltraHook API key 到使用者家目錄
echo "api_key: xxxxxx" > ~/.ultrahook
  • 啟動 UltraHook 服務
# ultrahook [-k ]  , API key 之前如果有設定可省略
ultrahook stripe http://dev.test.com/webhook
如果是 virtual host 要記得在 /etc/hosts 先設定好 IP
  • 如果成功就會開始轉發
Authenticated as danielhuang030test123
Forwarding activated...
http://stripe.danielhuang030test123.ultrahook.com -> http://dev.test.com/webhook

Reference

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Service Supervisor execution error

Problem

  • Laravel 5.5 文件 隊列 Supervisor 配置詳細解釋 Supervisor 的安裝與設定,不過實際在本機安裝時卻一直無法成功執行 php artisan queue:work
  • live EC2 安裝 Supervisor 使用相同設定卻沒有問題
  • 輸出 log 資訊有 php error:
PHP Parse error:  syntax error, unexpected '?' in /var/www/app/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php on line 233

Solution

  • 試著修改 Supervisor 設定檔卻一直沒有解決
  • 後來決定從 php error 訊息下手,google 後發現這個錯誤是因為使用 PHP 7.0 以才支援的 ?? 導致舊版本 PHP 無法判讀,不過從 cli 或是 web 看 PHP 的版本都是 7.1.8
  • 突然想到本機有裝phpbrew,因為系統內存在多版本,所以在 crontab 需要特別指定版本;推測 Supervisor 也是相同道理
  • 修改設定檔 command 參數,後來果然成功執行了!
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=/root/.phpbrew/php/php-7.1.8/bin/php /var/www/app/artisan queue:work --daemon --delay=3 --sleep=3 --tries=3
autostart=true
autorestart=true
user=root
numprocs=4
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/worker.log
文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Amazon CloudSearch

Info

Installation

  • Create a New Domain
  • NAME YOUR DOMAIN
    • Search Domain Name, 設定名稱
    • Desired Instance Type, 設定機器等級,預設 small
    • Desired Replication Count, 設定 Replication 數量,預設 1
  • CONFIGURE INDEX
    • Manual configuration, 手動設定
  • REVIEW INDEX CONFIGURATION
    • 這邊可以設定 index,除了 Name 以外,必須決定欄位的 Type
    • 一般文字設定 text 即可,如果有多個單詞時(ex. 分類名稱)可以設定 text-array
    • 另外 literal 也是一種文字類型,但是大小寫敏感,而且之後可以 group
    • 其他類型請參考文件
    • 之後可以透過程式建立,所以也可以略過不建立
  • SETUP ACCESS POLICIES
    • 設定權限,建議選擇 “Allow access to all services from specific IP(s)“,設定允許對外的 IP,多個 IP 時以逗號分隔
  • CONFIRM
    • 最後確認並完成建立,建立大概會需要 10 分鐘

Usage

Limit

  • 使用 Amazon CloudSearch 有一些限制,請參考說明文件
  • 參數 size, start 分頁時常使用,要注意的是 start 最多不可超過 10000;也就是透過這二個參數取得的資料最多只有前 10000 筆
  • 要取得 10000 筆以後的資料必須透過 cursor 取得

Laravel Package

Info

Settings

  • .env 設定參數
/project/.env
AWS_KEY=xxx
AWS_SECRET=xxx
 
# 之前建立的 Domain Name
CLOUDSEARCH_DOMAIN=xxx
# Dashboard 顯示的 Document Endpoint,必須包含 http
CLOUDSEARCH_ENDPOINT=http://doc-xxx-xxx-xxx.us-west-2.cloudsearch.amazonaws.com
# 不太清楚這個設定是什麼,我是填 AWS 區域
CLOUDSEARCH_REGION=us-west-2
  • config/cloud-search.php 設定
/project/config/cloud-search.php
// 修改從 .env 取得
'domain_name' => env('CLOUDSEARCH_DOMAIN'),
 
// 設定 index 欄位 Name 與 Type
'fields' => [
    'title' => 'text',
    'author' => 'text-array',
    'type' => 'literal',
],
 
// 設定 Eloquent 所在位置,ex. App/Models/Book.php
'model_namespace' => '\\App\\Models',
  • 透過 Command 建立 index
php artisan search:fields
  • 設定 Eloquent
/project/app/Models/Book.php
<?php
namespace App\Models;
 
use LaravelCloudSearch\Eloquent\Searchable;
 
class Book extends Model
{
    // 使用 Searchable
    use Searchable;
 
    // 必須實作這個方法,回傳 index 的值
    public function getSearchDocument()
    {
        return [
            'title' => $this->title,
            'author' => $this->authors->pluck('name')->toArray(),
            'type' => $this->type,
        ];
    }
}
  • 建立 index
php artisan search:index Book

Searching

  • 最基本的搜尋
// search "Kitten fluff"
$books = App\Models\Book::search('Kitten fluff')->get();
要留意的是基本搜尋只會找 Type 是 text, text-array 的欄位,如果需要尋找其他 Type 的欄位必須自建 searchBuilder
  • 新增額外設定,其他參數請參考文件
// search "Kitten fluff", default operator "or", add fields and weight
$books = App\Models\Book::searchBuilder()
    ->options('defaultOperator', 'or')
    ->options('fields', [
        'type^10',
        'title^5',
        'author',
    ])->term('Kitten fluff')->get();

Reference

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Info

  • Google 開發的一種靜態強型別、編譯型、並發型,並具有垃圾回收功能的程式語言。為了方便搜尋和識別,有時會將其稱為 Golang(from WIKI

Installation

# 2017/11 時最新版本是 1.9.2
wget https://redirector.gvt1.com/edgedl/go/go1.9.2.linux-amd64.tar.gz
# 解壓縮至 /usr/local/go
tar -C /usr/local -xzf go1.9.2.linux-amd64.tar.gz
  • 建立 Go 專案程式碼目錄,並修改其權限
# /var/golang
mkdir -p /var/golang
chmod 777 /var/golang -R
  • 加入 Go 相關參數(以 zsh 為例)
vi ~/.zshrc
export GOROOT=/usr/local/go
export GOPATH=/var/golang
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

Library

自動重載機制

go get github.com/pilu/fresh

Web Framework gin

go get github.com/gin-gonic/gin

MySQL driver

go get -u github.com/go-sql-driver/mysql

ORM

go get -u github.com/jinzhu/gorm

.env

go get github.com/joho/godotenv

Reference

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Info

  • 一種文件導向的資料庫管理系統

Installation

Setting

設定可連入的 ip 與 port

  • MongoDB 預設只開放給 localhost,必須修改設定檔
sudo vi /etc/mongod.conf
net:
  port: 27017
  # 0.0.0.0 對所有 ip 開放
  bindIp: 0.0.0.0
# 重新啟動
sudo service mongod restart

建立權限

  • MongoDB 預設沒有權限,不需要登入帳號密碼即可操作資料
  • 如果需要建立權限,必須先建立管理者(admin DB 的 Users)
# 進入 mongo
mongo
# 進入 admin DB
use admin
# 建立管理者,回覆 Successfully added user: 表示成功
db.createUser(
    {
        user: "帳號",
        pwd: "密碼",
        roles: [ { role: "root", db: "admin" } ]
    }
)
# 使用管理者權限,回覆 1 表示成功
db.auth("帳號", "密碼");
  • 或是在進入 mongo 前登入
mongo -u "帳號" -p "密碼" --authenticationDatabase "admin"

預設開啟帳號驗證

sudo vi /etc/mongod.conf
#security:
security.authorization: enabled
# 重新啟動
sudo service mongod restart

Management Tool

PHP Driver

phpbrew

  • 直接安裝 ext 即可
# PHP 7.0 以上
phpbrew ext install mongodb

原生 php

# 根據主機使用的 PHP 版本選擇安裝 dev 版本
sudo apt install php-pear php7.1-dev
# 更新 pecl
sudo pecl channel-update pecl.php
# 安裝 mongodb
sudo pecl install mongodb
  • 安裝成功後會顯示 so 檔位置
Build process completed successfully
Installing '/usr/lib/php/20160303/mongodb.so'
install ok: channel://pecl.php.net/mongodb-1.3.0
configuration option "php_ini" is not set to php.ini location
You should add "extension=mongodb.so" to php.ini
  • 新增至 php.ini(apache & cli)
sudo vi /etc/php/7.1/apache2/php.ini
sudo vi /etc/php/7.1/cli/php.ini
    ;extension=php_xsl.dll
    extension=mongodb.so

Laravel Package

  • /project/config/database.php
    // mongodb
    'mongodb' => [
        'driver'   => 'mongodb',
        'host'     => env('MONGODB_HOST'),
        'port'     => env('MONGODB_PORT'),
        'database' => env('MONGODB_DATABASE'),
        'username' => env('MONGODB_USERNAME'),
        'password' => env('MONGODB_PASSWORD'),
        'options'  => [
            'database' => env('MONGODB_DATABASE'),
        ]
    ],
  • Query Builder
// 需要指定連線與集合
$r = DB::connection('mongodb')->collection(MONGODB_COLLECTION_NAME)->get();
dd($r);
  • Model
  • /project/App/Models/Mongo/Test.php
<?php

    namespace App\Models\Mongo;

    use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

    class Test extends Eloquent
    {
        /**
         * guarded attributes
         *
         * @var array
         */
        protected $guarded = [];

        /**
         * collection name
         *
         * @var string
         */
        // protected $collection = 'tests';

        /**
         * connection name
         *
         * @var string
         */
        protected $connection = 'mongodb';
    }
// 跟一般 model 使用沒有差別
$r = $this->model->where('time', '=', '2017-09-14 19:21')->take(3)->get();
dd($r);

Reference

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Info

  • 加入 js 檔案時,也可以同時設定引用 jQuery 等 lib
  • add_action('wp_enqueue_scripts', 'gtm_scripts');
    function gtm_scripts() {
        // product category page
        if (is_product_category()) {
            wp_enqueue_script('product-category', get_stylesheet_directory_uri() . "/js/gtm/product_category.js", array('jquery'));
            return;
        }
    }
  • 要注意的是引用 jQuery 後因為避免版本衝突,引用的 js 中不能使用「$」要改用「jQuery」
  • jQuery(function() {
      console.log('GTM product-category page');
      dataLayer.push({'event': 'catpg'});
    });

Reference

  1. https://developer.wordpress.org/reference/functions/wp_enqueue_script/
文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Info

  • L2TP 協定自身不提供加密與可靠性驗證的功能,可以和安全協定搭配使用,從而實現資料的加密傳輸。經常與 L2TP 協定搭配的加密協定是IPsec,當這兩個協定搭配使用時,通常合稱L2TP/IPsec

Installation

git clone https://github.com/hwdsl2/docker-ipsec-vpn-server.git
cd docker-ipsec-vpn-server
sudo cp vpn.env.example vpn.env
sudo vi ~/docker-ipsec-vpn-server/vpn.env
# IPSec 的公鑰,建議字串長度長一點
VPN_IPSEC_PSK=PASS

# 預設使用者名稱
VPN_USER=tester

# 預設使用者密碼(明碼)
VPN_PASSWORD=aaaaaa

# 分配 L2TP 私人 IP 網段範圍
VPN_L2TP_NET=172.16.0.013
VPN_L2TP_LOCAL=172.16.0.1
VPN_L2TP_POOL=172.16.0.10-172.23.255.250

# 分配 XAUTH 私人 IP 網段範圍
VPN_XAUTH_NET=172.24.0.013
VPN_XAUTH_POOL=172.24.0.10-172.31.255.250

# 指定 DNS 位置
VPN_DNS_SRV1=XXX.XXX.XXX.XXX
VPN_DNS_SRV2=XXX.XXX.XXX.XXX
DNS_SRV1=XXX.XXX.XXX.XXX
DNS_SRV2=XXX.XXX.XXX.XXX
    - ./users/ppp:/etc/ppp
    - ./users/ipsec.d:/etc/ipsec.d
# 建議先不要背景執行,有錯誤可以比較容易發現
docker-compose up
  • 網路上常見的安裝方式:
  • 二種方法我都試過,但是安裝的程式與設定也很多;不意外的又卡關了。這時候我又想起了 docker,果然網路上又有大大提供整合好的 docker images,測試使用 hwdsl2/docker-ipsec-vpn-server
  • docker 相關安裝請參考之前的說明
  • AWS 新增 Security groups,開啟 port UDP 1701, UDP 4500, UDP 500
  • git clone project
  • 複製並調整環境變數(其他變數請參考 run.sh
  • ~/docker-ipsec-vpn-server/vpn.env
  • 網段計算方式可以參考這裡
  • volume 使用者設定檔目錄,在 volumes 區塊新增
  • ~/docker-ipsec-vpn-server/docker-compose.yml
  • 建立 docker container
  • 如果沒有問題,應該會看到下面的畫面;包含 IP、公鑰、預設的使用者帳號與密碼
  • 5185661_raw.jpg

Setting

管理使用者

sudo vi ~/docker-ipsec-vpn-server/users/ppp/chap-secrets
# Secrets for authentication using CHAP
# client  server  secret  IP addresses
"tester" l2tpd "aaaaaa" *
"test2" l2tpd "aaaaaa" *
# $1$x2I2244y$mWuO1pmeYNwpdOqow5xbo.
openssl passwd -1 "aaaaaa"
sudo vi ~/docker-ipsec-vpn-server/users/ipsec.d/passwd
# Secrets for authentication using CHAP
# client  server  secret  IP addresses
tester:$1$x2I2244y$mWuO1pmeYNwpdOqow5xbo.:xauth-psk
test2:$1$x2I2244y$mWuO1pmeYNwpdOqow5xbo.:xauth-psk
  • 修改 L2TP/IPsec 設定檔(明碼),新增使用者 test2
  • ~/docker-ipsec-vpn-server/users/ppp/chap-secrets
  • 修改 Cisco IPsec 設定檔(password),新增使用者 test2
  • Password
  • ~/docker-ipsec-vpn-server/users/ipsec.d/passwd
  • 不需要重新啟動 IPSec,儲存後新帳號即可使用

管理使用者 in container

docker exec -it ipsec-vpn-server env TERM=xterm bash -l
apt-get update && apt-get -y install vim
  • 進入 docker container
  • 安裝編輯器 vim
  • 修改設定檔
  • 不需要重新啟動 IPSec,儲存後新帳號即可使用

修改 PSK 設定

%any  %any  : PSK "PASS"
  • /etc/ipsec.secrets

修改 Private IP 設定

ip range = 172.16.0.10-172.31.255.250
local ip = 172.16.0.1
  • /etc/xl2tpd/xl2tpd.conf

修改 DNS 設定

ms-dns XXX.XXX.XXX.XXX # 同一台主機可以設定為 local ip
  • /etc/ppp/options.xl2tpd

重啟服務

sudo ipsec restart
sudo service xl2tpd restart

Other

Windows 10 連線發生錯誤

REG ADD HKLM\SYSTEM\CurrentControlSet\Services\PolicyAgent /v AssumeUDPEncapsulationContextOnSendRule /t REG_DWORD /d 0x2 /f
  • Q: 如果連線發生錯誤,要特別修改登錄檔,似乎跟路由器有關係
  • A: 以系統管理員身分執行命令提示字元 cmd,輸入以下指令並執行

無法使用 VPN 指定 DNS

  • Q: Windows 10 VPN 連線成功,但「自動取得 DNS 伺服器位址」時卻沒有透過 VPN 指定的 DNS 解析網址,只有在指定 DNS 伺服器位址後才會有效
  • A: 網路連線 > VPN > 右鍵「內容」 > 分頁「網路功能」 > 網際網路通訊協定第 4 版 (TCP/IPv4) > 內容 > 進階 > 自動計量不勾選 > 輸入框設定值: 15

Reference

文章標籤

danielhuang030 發表在 痞客邦 留言(0) 人氣()

Close

您尚未登入,將以訪客身份留言。亦可以上方服務帳號登入留言

請輸入暱稱 ( 最多顯示 6 個中文字元 )

請輸入標題 ( 最多顯示 9 個中文字元 )

請輸入內容 ( 最多 140 個中文字元 )

reload

請輸入左方認證碼:

看不懂,換張圖

請輸入驗證碼