2022年8月23日 星期二

Cloudflare 1.1.1.1 FOR FAMILIES 提供阻擋惡意網站與成人網站的 DNS 查詢服務


最近跟朋友聊天,才發現 Cloudflare 除了提供 1.1.1.1 反應速度極快的 DNS 查詢服務外,還有提供阻擋惡意網站、成人網站的 DNS 查詢服務!當發現是惡意網站時,直接給予 0.0.0.0 (查不到) 的回饋,如此使用者在瀏覽網站時,不小心點擊到的惡意連結也不會瀏覽到,對於家裡有長輩、小孩的環境來說,真的很不錯。

大概五六年前在幫公司做 使用者生成內容 (User-generated content) 時,再加上規劃權限機制,打算從大家公開的資料中,整理出熱門的網站/影片連結出來,這時就會踩到有人擺了色情網站等問題,那時則是做了一套 URL Checker/Filter (SPAM) 機制,透過網域黑名單做的。現在,單純用 Cloudflare 提供的 DNS 來查詢也能直接達到類似的效果。

Cloudflare 1.1.1.1 FOR FAMILIES: https://one.one.one.one/family/
  • 1.1.1.1
    • 與 Google 8.8.8.8, 8.8.4.4 同樣效果但標榜更快、更注重隱私
    • 2018.04.01 開始的服務
  • 1.1.1.2, 1.0.0.2
    • 可阻擋惡意網站: Malware Blocking Only
  • 1.1.1.3, 1.0.0.3
    • 可阻擋惡意網站+成人網站: Malware and Adult Content Blocking Together
如此,在疫情後常態在家上課時,小孩拿手機平板連到家裡的 WIFI AP ,這時在 WIFI AP 的 DHCP 設置 DNS = 1.1.1.3 , 1.0.0.3 後,就可以簡單防護到所有連到此 WIFI AP 的設備,可防止小孩誤點、誤連到惡意網站和成人網站內容,畢竟有不少惡意網站/成人網站仍會買流量的,立即能避開一堆奇怪廣告。當然,對長輩來說也有一樣的效果。

圖:TP-Link WIFI AP 之 DHCP 設定 主要 DNS / 次要 DNS

其他:

2022年8月20日 星期六

Go 開發筆記 - 簡易 WebSocket Client 練習,WSS 與 Skip SSL Check

公司的 WebSocket Server 使用 node.js Primus 建構服務,最近正在調整架構,弄隻 WebSocket Client 交叉比對,這時就想到 Golang 可以練一下 XD 預設先以 PTT 的 WebSocket 為例 wss://ws.ptt.cc/bbs 練習,而 PTT WebSocket 連線時,有檢查 Request Header 的 Origin 欄位的,完整的用法請直接使用 https://term.ptt.cc 。

實作上,直接用 Gorilla WebSocket 即可,用他建制 WebSocket server 跟 client。

此外,對於 WebSocket over SSL (wss) 連線瑣事上,若要處理 SKIP SSL Check 這件事,可以這樣處理:

// https://pkg.go.dev/crypto/tls
type zeroSource struct{}
func (zeroSource) Read(b []byte) (n int, err error) {
    for i := range b { 
        b[i] = 0 
    }   
    return len(b), nil 
}

func main() {

// ...

    var dialer ws.Dialer
    if *skipSSLCheck {
        fmt.Println("[IFNO] Skip SSL check")
        // https://github.com/gorilla/websocket/blob/master/client.go
        // https://github.com/gorilla/websocket/blob/master/tls_handshake.go
        dialer = ws.Dialer{
            Subprotocols: []string{},
            ReadBufferSize: 2048,
            WriteBufferSize: 2048,
            TLSClientConfig: &tls.Config{
                Rand: zeroSource{},
                InsecureSkipVerify: true,
            },
        }
    } else {
        dialer = ws.Dialer{
            Subprotocols: []string{},
            ReadBufferSize: 2048,
            WriteBufferSize: 2048,
        }
    }
    fmt.Println("[IFNO] try to connect to: ", connectToURL)

// ...

}

至於跟 node.js Primus WebSocket server 溝通時,會有 PING/PONG 的 heartbeat 檢驗,目前偷懶等收到 server 詢問時才回,此外,實際上可以靠 messageType (Control Messages) 來判斷:

    go func() {
        defer func() {
            wg.Done()
        }()
        for {
            _, p, err := conn.ReadMessage()
            if err == nil {
                cmd := string(p)
                fmt.Println("SERVER> ", cmd)

                    if strings.Index(cmd, "\"primus::ping::") >= 0 {
                        text := fmt.Sprintf("\"primus::ping::%d\"", time.Now().UnixMilli())
                        fmt.Println("CLIENT:AUTO> [",text,"]")
                        conn.WriteMessage(ws.TextMessage, []byte(text))
                    }

            } else {
                fmt.Println("SERVER:ERROR> ", err)
                break
            }
        }
        fmt.Println("[IFNO] server error")
    }()

更多完整的資訊,就直接參考 github.com/changyy/go-ws-client

2022年8月8日 星期一

PHP 開發筆記 - 在 Windows 10 上配置 cmd line 開發環境


這個故事說來話長,我本身不會在 Windows 開發,但為了同事只好配置環境出來,交叉比對運作的問題。就筆記一下,這次要做的事就弄到純 cmd line 開發環境:

安裝:

如此,在 cmd 就可以靠純指令工作,像是 composer install ,而在 cmd line 中有 vim 編輯器,可以快速編輯小東西。

2022年8月3日 星期三

PHP 開發筆記 - 關於 CodeIgniter4 starter app / PHP Coding Standards Fixer v3.9.5 / PHP 7.4 @ macOS 與 Windows

之前初探 PHP Coding Standards Fixer (php-cs-fixer) 時,略知預設跑下去已經有一定水準的 Coding Style 制約機制,然而,工作上引導同事在使用時,碰到了一些雷區。

首先是用 CodeIgniter 4 官方文件建立出的資料後,要跑 PHP Coding Standards Fixer 時會出現要修正語法的問題

```
// https://www.codeigniter.com/user_guide/installation/installing_composer.html
% composer create-project codeigniter4/appstarter project-root
% ./vendor/bin/php-cs-fixer fix --dry-run -v .
PHP CS Fixer 3.9.5 Grand Awaiting by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.30
Loaded config CodeIgniter4 Coding Standards from "/path/./.php-cs-fixer.dist.php".
Using cache file ".php-cs-fixer.cache".
Paths from configuration file have been overridden by paths provided as command arguments.
.....F......................................F.............                                                                            58 / 58 (100%)
Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error
   1) app/Config/Logger.php (ordered_imports)
   2) app/Views/errors/html/error_exception.php (braces, unary_operator_spaces, not_operator_with_successor_space)

Checked all files in 1.104 seconds, 16.000 MB memory used
```

然後故意降版本到 v3.8.0 又可以正常

```
% mv composer.json composer.json-bak
% composer require friendsofphp/php-cs-fixer:3.8.0 --dev
% ./vendor/bin/php-cs-fixer fix --dry-run -v .
PHP CS Fixer 3.8.0 BerSzcz against war! by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.30
Loaded config default.
Using cache file ".php-cs-fixer.cache".
..........................................................                                                                            58 / 58 (100%)
Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error

Checked all files in 0.303 seconds, 14.000 MB memory used
```

為了避免未來同事不同平台開發的困局,就來安分地寫一下 .php-cs-fixer.dist.php 檔案吧!也順道研究到 CodeIgniter 也有個 CodeIgniter/coding-standard 規範,接著參考 github.com/CodeIgniter/coding-standard#setup 一步一步測試

```
% cat .php-cs-fixer.dist.php
<?php

use CodeIgniter\CodingStandard\CodeIgniter4;
use Nexus\CsConfig\Factory;

return Factory::create(new CodeIgniter4())->forProjects();

% ./vendor/bin/php-cs-fixer fix --dry-run -v .
PHP CS Fixer 3.9.5 Grand Awaiting by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.30
Loaded config CodeIgniter4 Coding Standards from "/path/./.php-cs-fixer.dist.php".
Using cache file ".php-cs-fixer.cache".
Paths from configuration file have been overridden by paths provided as command arguments.
.....F......................................F.............                                                                            58 / 58 (100%)
Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error
   1) app/Config/Logger.php (ordered_imports)
   2) app/Views/errors/html/error_exception.php (braces, unary_operator_spaces, not_operator_with_successor_space)

Checked all files in 1.104 seconds, 16.000 MB memory used
```

開始先找一下怎樣略過那兩個檔案的用法:

```
% cat .php-cs-fixer.dist.php
<?php
use CodeIgniter\CodingStandard\CodeIgniter4;
use Nexus\CsConfig\Factory;
use PhpCsFixer\Finder;

// https://github.com/codeigniter4/CodeIgniter4/blob/develop/.php-cs-fixer.dist.php
$finder = Finder::create()
->files()
->notPath([
'app/Config/Logger.php',
'app/Views/errors/html/error_exception.php',
]);

// https://github.com/NexusPHP/cs-config/blob/develop/src/Factory.php
//return Factory::create(new CodeIgniter4())->forProjects();
return Factory::create(new CodeIgniter4(), [], [
'finder' => $finder,
])->forProjects();

% ./vendor/bin/php-cs-fixer fix --dry-run .
Loaded config CodeIgniter4 Coding Standards from "/path/./.php-cs-fixer.dist.php".
Using cache file ".php-cs-fixer.cache".

Checked all files in 0.032 seconds, 14.000 MB memory used
```

接著去 Windows 跑:

```
C:\path>.\vendor\bin\php-cs-fixer fix --dry-run .
PHP CS Fixer 3.9.1 Grand Awaiting by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 7.4.30
Loaded config CodeIgniter4 Coding Standards from "C:\path\.\.php-cs-fixer.dist.php".
Using cache file ".php-cs-fixer.cache".
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF          56 / 56 (100%)
Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error

   1) app\Common.php (line_ending)
  ...
  55) tests\_support\Libraries\ConfigReader.php (line_ending)
  56) tests\_support\Models\ExampleModel.php (line_ending)

Checked all files in 1.187 seconds, 16.000 MB memory used
```

最後再加個 line_ending 來處理一下:

```
% cat .php-cs-fixer.dist.php
<?php
use CodeIgniter\CodingStandard\CodeIgniter4;
use Nexus\CsConfig\Factory;
use PhpCsFixer\Finder;

// https://github.com/codeigniter4/CodeIgniter4/blob/develop/.php-cs-fixer.dist.php
$finder = Finder::create()
->files()
->notPath([
'app/Config/Logger.php',
'app/Views/errors/html/error_exception.php',
]);

// https://github.com/NexusPHP/cs-config/blob/develop/src/Factory.php
//return Factory::create(new CodeIgniter4())->forProjects();
return Factory::create(new CodeIgniter4(), [], [
'finder' => $finder,
// https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues/3955
'lineEnding' => PHP_EOL,
])->forProjects();
```

收工!

2022年7月30日 星期六

Go 開發筆記 - 透過 Electron 實現 PC app GUI 之 go-astilectron / go-astilectron-bundler / go-astilectron-bootstrap


前陣子練習 Golang 後,除了建制後端 API 及網頁服務外,在想該怎樣做個 Windows / macOS 的 PC App 時,逛了一下熱門的 GUI 套件,有常見的 QT, GTK3/GTK4 等等,最後想起 Electron 這套,找了一下果真也有人串好 Go 與 Electron 整合方式。就來試試看 go-astilectron 這套吧!

處理的項目:
專案初始化:

% cat main.go 
package main

import (
    "github.com/asticode/go-astilectron"
)

func main() {

}

% go mod init github.com/changyy/study-go-electron
% go mod tidy

接著切一個目錄 web 做網頁開發管理:

% tree -L 1 web
web
├── README.md
├── dist
├── env_nvm.sh
├── env_vim.sh
├── node_modules
├── package-lock.json
├── package.json
├── src
├── webpack.common.js
├── webpack.development.js
└── webpack.production.js

3 directories, 8 files

其中 package.json 內使用 webpack 安置開發模式和發版封裝、使用 eslint 做 coding style 規範:

% cat web/package.json | jq '.scripts'
{
  "eslint": "eslint --ext .js src/",
  "eslint-fix": "eslint --fix --ext .js src/",
  "watch": "webpack --config webpack.development.js --watch",
  "start": "webpack serve --config webpack.development.js --open",
  "build": "webpack --config webpack.production.js"
}

而 web 程式碼入口點:

% tree web/src     
web/src
├── index.html
└── js
    ├── helper-old-style.js
    ├── helper.js
    └── index.js

1 directory, 4 files

試試看在 web/src/index.html 內,在 body.onload 內呼叫 hehe(),而 web/src/js/index.js 是一個統整區,而 webpack 在 production mode 會精簡程式碼,因此要匯出的功能都必須做點處理,像是故意埋在 windows.xx 等等,或是要調整 webpack 包裝的機制,如 output 區要多描述 libraryTarget 和 library 資訊,會自動綁定在 window.xx 環境。

回過頭來,關於 go astilectron 的使用,在不需要封裝成各平台的環境時,可以很簡單地用以下程式碼,並在根目錄用 `% go run .` 就可以運行了:

    a, _ := astilectron.New(log.New(os.Stderr, "", 0), astilectron.Options{
        AppName: "MyGoAstilectronProject",
    })
    defer a.Close()

    // Start astilectron
    a.Start()

    w, _ := a.NewWindow("./resources/app/index.html", &astilectron.WindowOptions{
        Center: astikit.BoolPtr(true),
        Height: astikit.IntPtr(600),
        Width:  astikit.IntPtr(600),
    })
    w.Create()

    // Blocking pattern
    a.Wait()

如此,在開發網頁版型時,單純在 web 目錄做事,如 npm run start 就可以喚起瀏覽器來瀏覽,等做完事後,在靠 npm run build 封裝到 web/dist 目錄以及複製一份到 resource/app 目錄中,後續就著靠 ~/go/bin/astilectron-bundler 封裝成 PC App,在封裝成 PC app 時,會面臨到 resources 目錄內的文件也得跟著封裝進去,也就是上述程式碼指定的 "./resources/app/index.html" 網頁資源,或者網頁位址要改成絕對路徑也是一招,但等同也要求使用此 PC app 者,下需要自行配置好網頁資料。

這時,就要使用 go-astilectron-bundler 跟 go-astilectron-bootstrap ,前者是編譯出 PC app ,後者是封裝好資源,使得執行 PC app 時,可以順道把對應的資源("./resources/app/")擺定位,這時程式碼就會變得稍微複雜一點,並且執行執行 `go run .` 不見得能常運行,將使得開發週期拉的很長(每次編譯要花幾分鐘的時間)

% ~/go/bin/astilectron-bundler cc
% time ~/go/bin/astilectron-bundler
...
~/go/bin/astilectron-bundler  63.79s user 10.56s system 108% cpu 1:08.21 total

最後,就把他配置成可以傳一個 -dev 參數,使用該參數時,不經過 ~/go/bin/astilectron-bundler 運行(運行的速度也只是小減 20% 時間而已 XD)

% go run . -dev

目前覺得用 Go 與 Electron framework 一起使用的好處還不夠強烈,以及整合開發的優勢頂多是用 Go 寫工具(api)等等,以及使 Electron 時,本來就是重度倚賴 HTML/JS/CSS 在 UI 呈現,因此直接 node.js 的整合優勢仍是最佳的。

更多資訊就在這邊:github.com/changyy/study-go-electron ,或是直接觀看 github.com/asticode/go-astilectron 內有提到 demo 範例,可以直接看 demo 內的實作。