2021/05/03

Install ClamAV in CentOS 7

安裝 ClamAV

sudo yum -y install epel-release
sudo yum -y install clamav clamd

# 如果有 selinux,要 enable selinux
sudo setsebool -P antivirus_can_scan_system 1

增加台灣病毒碼更新資料庫

sudo vi /etc/freshclam.conf

DatabaseMirror db.tw.clamav.net
DatabaseMirror clamav.stu.edu.tw

更新病毒碼

sudo freshclam

ClamAV update process started at Wed Oct 28 14:39:25 2020
daily database available for download (remote version: 25970)
Time: 17.0s, ETA: 0.0s [=============================>] 108.67MiB/108.67MiB
Testing database: '/var/lib/clamav/tmp.1a97b/clamav-3ea52eb38408f34bb5f4419b3286235e.tmp-daily.cvd' ...
Database test passed.
daily.cvd updated (version: 25970, sigs: 4336254, f-level: 63, builder: raynman)
main database available for download (remote version: 59)
Time: 17.3s, ETA: 0.0s [=============================>] 112.40MiB/112.40MiB
Testing database: '/var/lib/clamav/tmp.1a97b/clamav-087960cd134405741c214b5dd9915ec8.tmp-main.cvd' ...
Database test passed.
main.cvd updated (version: 59, sigs: 4564902, f-level: 60, builder: sigmgr)
bytecode database available for download (remote version: 331)
Time: 0.4s, ETA: 0.0s [=============================>] 289.44KiB/289.44KiB
Testing database: '/var/lib/clamav/tmp.1a97b/clamav-4905f2da7d8e4b680242ba674f8d9ced.tmp-bytecode.cvd' ...
Database test passed.
bytecode.cvd updated (version: 331, sigs: 94, f-level: 63, builder: anvilleg)

設定自動更新病毒碼

mkdir -p /var/log/clamav
chown -R clamupdate:clamupdate /var/log/clamav/

sudo vi /etc/freshclam.conf
UpdateLogFile /var/log/clamav/freshclam.log

增加自動更新病毒碼 cronjob

vi /etc/cron.daily/freshclam.sh

#!/bin/sh
/usr/bin/freshclam --quiet -l /var/log/clamav/freshclam.log


chmod 755 /etc/cron.daily/freshclam.sh

另一種設定自動更新的方式,是直接啟動 clamav-freshclam.service

設定 clamd

vi /etc/clamd.d/scan.conf

LocalSocket /var/run/clamd.scan/clamd.sock

# 啟用紀錄
LogFile /var/log/clamd/clamd.scan

# 啟用記錄訊息時間
LogTime yes

# 啟用LocalSocket
LocalSocket /var/run/clamd.scan/clamd.sock

# 啟用ExtendedDetecionInfo
ExtendedDetectionInfo yes

# 啟用PidFile
PidFile /var/run/clamd.scan/clamd.pid

產生 clamd log file

mkdir -p /var/log/clamd/
touch /var/log/clamd/clamd.scan
chown -R clamscan:clamscan /var/log/clamd

啟動 clamd

sudo systemctl enable clamd@scan
sudo systemctl start clamd@scan

設定每日自動掃瞄特定目錄

儲存記錄檔於 /var/log/clamscan_daily.log

mkdir -p /var/log/clamscan

vi /etc/cron.daily/clamscan.sh

#!/bin/sh
echo "************" >> /var/log/clamscan/clamscan_daily.log
date '+%Y-%m-%d %T' >> /var/log/clamscan/clamscan_daily.log
/usr/bin/clamscan -i -r /var/www/html >> /var/log/clamscan/clamscan_daily.log
chmod 755 /etc/cron.daily/clamscan.sh

logrotate

vi /etc/logrotate.d/clamscan.logrotate

/var/log/clamscan/clamscan_daily.log {
   missingok
   rotate 30
   daily
}

修改 clamscan.logrotate

vi /etc/logrotate.d/clamav-update

/var/log/clamav/freshclam.log {
    monthly
    notifempty
    missingok
    postrotate
        systemctl try-restart clamav-freshclam.service
    endscript
}

安裝 LMD

# 安裝 EPEL
yum -y install epel-release
# 安裝 mailx
yum install mailx
wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
tar -zxvf maldetect-current.tar.gz

cd maldetect-1.6.4/
./install.sh

ln -s /usr/local/maldetect/maldet /bin/maldet
hash -r

LMD 預設安裝目錄在 /usr/local/maldetect/ , 裡面的 conf.maldet 就是 LMD 的設定檔, 開啟 LMD 的設定檔

vi /usr/local/maldetect/conf.maldet

# 如果要發 email,要改成 1
email_alert="0"
email_addr="user@domain"

quarantine_hits="1"
quarantine_clean="1"

scan_clamscan="1"

掃描後查看 report

maldet -e list

# read report
maldet –report SCANID

# clean report
maldet --clean SCANID

測試 LMD

mkdir -p /var/www/LMDtest
cd /var/www/LMDtest
wget https://www.eicar.org/download/eicar.com 
wget https://www.eicar.org/download/eicar.com.txt 
wget https://www.eicar.org/download/eicar_com.zip 
wget https://www.eicar.org/download/eicarcom2.zip

chown -R httpd:httpd /var/www/LMDtest

掃描

maldet -a /var/www/LMDtest

看 report

maldet --report 201028-1639.16052

PATH:          /var/www/LMDtest/
TOTAL FILES:   4
TOTAL HITS:    4
TOTAL CLEANED: 0

FILE HIT LIST:
{HEX}EICAR.TEST.3 : /var/www/LMDtest/eicar.com => /usr/local/maldetect/quarantine/eicar.com.575417503
{HEX}EICAR.TEST.3 : /var/www/LMDtest/eicarcom2.zip => /usr/local/maldetect/quarantine/eicarcom2.zip.2371612503
{HEX}EICAR.TEST.3 : /var/www/LMDtest/eicar.com.txt => /usr/local/maldetect/quarantine/eicar.com.txt.17479243
{HEX}EICAR.TEST.3 : /var/www/LMDtest/eicar_com.zip => /usr/local/maldetect/quarantine/eicar_com.zip.8340145
===============================================
Linux Malware Detect v1.6.4 < proj@rfxn.com >

隔離區 /usr/local/maldetect/quarantine/

# 刪除隔離區檔案
rm -rf /usr/local/maldetect/quarantine/*

References

Install and configure LMD and Clam AntiVirus on CentOS 7

How to Install and Use Linux Malware Detect (LMD) with ClamAV as Antivirus Engine

CentOS7 安裝防毒軟體 ClamAV

How to Install ClamAV on CentOS 7: A Step-by-Step Guide

CENTOS 7 安裝ClamAV

2021/04/29

Android Service

Android Service

 

Android Service

簡述

  • Service可以在背景不斷的工作,直到停止或是系統無法提供資源為止。
  • Service 需要透過某Activity 或者其他Context 物件來啟動。
  • Service不需要和 user 互動,所以沒有操作介面。
  • 生命週期與Activity是各自獨立的,Activity就算關閉,Service仍然可以繼續執行。
  • 類似 BroadcastReceiver,需要定義一個繼承 Service 的類別,並覆寫其中的生命週期函數,最後在AndroidManifest.xml中宣告才能使用
  • Service可以同時支援 StartedBind 兩種模式。在這種情況下,Service 需要等到兩種模式都被關閉才會觸發onDestroy()事件。
  • Service 只有第一次被啟動時,會執行onCreate(),若重複啟動則不會執行onCreate()
  • Service的運作優先權相當的高,一般來說除非系統資源耗盡,否則 Android 不會主動關閉一個已被啟動的Service。一旦系統有足夠的資源,被 Android 關閉的Service也會被重新啟動。
  • 兩者都需要在AndroidManifest.xml宣告

Service 生命週期

根據執行方式的不同,啟動Service分為兩種,注意只有黃色區塊不一樣: 圖左- Started 模式;圖右- Bind 模式,並根據不同模式複寫白色框框裡的函式。

Started 模式

啟動此模式的 Service,即便退出 Activity 也不會影響 Service 的運行,且Activity無法調用 Service 的方法。

  • 啟動 Service 的方式

    • Client side (Activity):Context.startService(intent)
  • 關閉 Service 的方式

    • Client side (Activity):Context.stopService()
    • Service inside:stopSelf()
  • onStartCommand() 最後需要回傳一個常數,這些常數定義在 Service 類別中。該回傳值是用在如果這個 Service 被 Android 作業系統終止後的行為:

    • Service.START_STICKY Service 如果被中止的話會自動重啟。用在onStartCommand()方法中不需要依賴Intent傳入的資料就可以執行的時候(重新啟動時重新傳入的Intent會是null)。這也是預設使用super.onStartCommnad()的回傳值。
    • Service.START_NOT_STICKY Servcie 如果被中止的話不重新啟動,用在onStartCommand()方法中所執行的工作需要依賴Intent物件內帶進來的參數。
    • Service.START_REDELIVER_INTENT START_STICKY 差不多,但 Android 會在中止 Service 之前將Intent保留下來,等待重新啟動時再將原本的Intent物件交還給onStartCommand()事件。

 

Bind 模式

啟動此模式的 Service,會伴隨著與調用者(Client)一起存活或是退出,當Activity退出Service的運行也會一起終止。

  • 啟動 Service 的方式

    • Client side (Activity):Context.bindService(intent, mServiceConnection, int flags)。其中第二個參數為ServiceConnection 物件,當bindService()綁定成功後,會呼叫此物件內的 onServiceConnected 函式,此函式會接收到由 Service 內的 onBind() 所丟出來的 IBinder 物件來直接操作 Service 內各個 public 的 method。 (ServiceConnection物件實作方式參考下方連結)
  • 關閉 Service 的方式

    • Service inside: unbindService(mServiceConnection);

 

解析 startService

透過以下範例了解startService運作流程,若需詳細程式碼請參考

測試角色

Service 端

  • TestService

Client 端

  • MainActive

結果

这里写图片描述

 

生命週期流程

这里写图片描述

 

再次分析onStartCommand() 的回傳值

  • START_NOT_STICKY

    • 表示當 Service 運行的 process 被 Android 系統強制殺掉之後,不會重新創建該 Service,當然如果在其被殺掉之後一段時間又調用了 startService,那麼該 Service 又將被實例化。
    • Ex:某個 Service 需要定時從 server 獲取最新數據:通過一個定時器每隔指定的N分鐘讓定時器啟動 Service 去獲取 server 的最新數據。當執行到 ServiceonStartCommand 時,在該方法內再規劃一個N分鐘後的定時器用於再次啟動 Service 並開闢一個新的執行緒去執行網絡操作。假設 Service 在從 server 獲取最新數據的過程中被 Android 系統強制殺掉,Service 不會再重新創建,這也沒關係,因為再過N分鐘定時器就會再次啟動該 Service 並重新獲取數據。
  • START_STICKY

    • 表示 Service 運行的 process 被 Android 系統強制殺掉之後,Android 系統會將該 Service 依然設置為 started 狀態(即運行狀態),但是不再保存 onStartCommand 方法傳入的 intent 對象,然後 Android 系統會嘗試再次重新創建該 Service,並執行 onStartCommand 回調方法,但是 onStartCommand 回調方法的 Intent 參數為 null,也就是 onStartCommand 方法雖然會執行但是獲取不到 intent 信息。
    • Ex:如果 Service 可以在任意時刻運行或結束都沒什麼問題,而且不需要 intent 信息,那麼就可以在 onStartCommand 方法中返回 START_STICKY,比如一個用來播放背景音樂功能的 Service 就適合返回該值
  • START_REDELIVER_INTENT

    • 表示 Service 運行的 process 被 Android 系統強制殺掉之後,與返回 START_STICKY 的情況類似,Android 系統會將再次重新創建該 Service,並執行 onStartCommand 回調方法,但是不同的是,Android 系統會再次將 Service 在被殺掉之前最後一次傳入 onStartCommand 方法中的 Intent 再次保留下來,並再次傳入到重新創建後的 ServiceonStartCommand 方法中,這樣我們就能讀取到 intent 參數。
    • Ex:如果 Service 需要依賴具體的 Intent 才能運行(需要從 Intent 中讀取相關數據信息等),並且在強制銷毀後有必要重新創建運行,那麼這樣的 Service 就適合。

解析 bindService

Client 與 Service 在同一個 App 中

透過以下幾個範例了解 bindService 的運作流程,若需詳細程式碼請參考

測試角色

Service 端

  • TestService

Client 端

  • 兩個 Activity,分別為 Active AActive B
  1. Activity A
  2. Activity B

測試流程

測試一

步驟
  • Activity A

    • click bindService
    • click unbindService
結果

測試二

步驟
  • Activity A

    • click bindService
    • click Finish
結果

測試三

步驟
  • Activity A

    • click bindService
    • click start Activity B
  • Activity B

    • click bindService
    • click unbindService
    • click Finish
  • Activity A

    • click unbindService
結果

生命週期流程

Client 與 Service 在同一個 App 中

參考

淺談 Service v.s. thread

  • 看似都是在背景運作,但實際上ServiceThread 沒有任何關係。

  • Service 是運行於主執行緒(Main Thread)上,故若在此執行太耗時的任務,依然會出現 ANR。

  • Thread 是用於開啟一個子執行緒(Child thread),去執行一些耗時作不會阻塞主執行緒的運行。

  • Activity 很難對 Thread 進行控制:

    • Activity 被銷毀後卻沒有主動停止 thread,就會造成没有辦法可以再重新獲取到之前建立的 thread 的實例。
    • 在某 Activity 中建立的 thread,另一個 Activity 無法對其進行操作。
  • Service 方便取得控制權:

    • Activity 被銷毀,其他的 Activity 都可以與 Service 重新進行關聯,就又能夠獲取到原有 Service 中 Binder 的實例。
    • 使用 Service 來處理後台任務,Activity 可以放心地 finish,完全不需要擔心無法對後台任務進行控制的情況。
  • 如果在Service內部做一些很耗時的任務,可以在Service內部建立一個執行緒來處理。因為Service是跑在主執行緒中,會影響到 UI 操作或是阻擋主執行緒的運行

    • ex:在後台播放多媒體檔案會需要檢查SD、在後台紀錄 gps 資訊的變換等等

Ref.

Service背景執行程式

《Android》『Service』- 背景執行服務的基本用法

Android中startService的使用及Service生命周期

Android中bindService的使用及Service生命周期

Android Service和Thread区别

 

2021/04/26

Acoustic Echo Cancellation (AEC)

回音就是發話端發出的聲音,在經過一陣子以後,自己又聽到自己發出的聲音,通常音量會變比較小一點,但還是能識別出來是自己發出的聲音。

回音通常分為兩種:線路回音、聲學回音。

線路回音是因為傳送語音的實體線路造成的,通常是因為電信局之間是使用四線,而電信局到用戶端是兩芯線,中間會有四線、二線的轉換混合器,如果阻抗不匹配(使用不同型號的電線,或是沒有使用負載線圈),就會導致混合器接收線路的語音訊號,外溢流到發送線路上,因此產生了回音。

聲學回音,就是發話端發出的聲音,傳送到接收端後,接收端以 speaker 播放出來,在麥克風收音時,同時又把 speaker 播放的聲音收錄進去,傳送回到發話端,通常造成這樣的回音的終端,並不會知道自己造成了回音,讓另一端聽到回音。

聲學回音又分為直接回音和間接回音。直接回音是指 speaker 播放出來的聲音未經任何反射直接進入麥克風,這種回音延遲最短。間接回音是指 speaker 播放的聲音經不同的路徑一次或多次反射後進入麥克風所產生的回音集合,有可能是房間的牆壁反射造成的。

回音消除主要包含兩個步驟:線性自適應濾波和非線性處理。

線性自適應濾波就是對 fe=f(fs) 求解,建立遠端回聲的語音模型,進行第一輪回音消除。

非線性處理又分為兩個步驟:殘留回音處理和非線性剪切處理。殘留回音處理進行第二輪回音消除,處理殘留回音;非線性剪切處理就是對衰減量達到閾值的語音信號進行比較激進的剪切處理。

自適應濾波演算法

有兩個系列:LMS 與 RLS

LMS 比較穩定,運算量小,比較容易建置與實作。RLS 執行時收斂速度較快,缺點是運算量大。

LMS: Least Mean Square Algorithm

LMS 是最廣泛使用的濾波器演算法,計算過程只有加法與乘法。做法是讓輸出的誤差訊號的均方值最小化。

LMS 的 adaptation step size 是用來調整加權參數的修正速度,數值太小會讓收斂速度變慢,太大會造成發散。

NLMS: Normalized LMS

重新定義 LMS 中的 𝜇 (adaptation step size),讓 𝜇 會隨輸入訊號的 normalization 而改變,提升收斂的穩定性。

RLS: Recursive Least Squares Algorithm

RLS 演算法目標是將輸出誤差信號平方值總和最小化

open source AEC

目前 open source 的 AEC 演算法有 speex 與 webrtc,兩種都是使用自適應濾波 NLMS。

speex 是使用 MDF 雙濾波結構,用前綠波跟本次濾波的結果來調整濾波器的參數,濾波器的長度很長。

webrtc AEC 比較複雜,包含了 delay 估計, NLMS 及 NLP,舒適噪音。NLMS 的部分只用了 12 block。

目前 speex AEC 用在嵌入式系統,硬體不需要延時模組,速度比較快。webrtc AEC 用在軟體。

References

聲學回聲消除(Acoustic Echo Cancellation)原理與實現

回聲消除基本介紹

音視頻社交中回聲消除技術是如何實現的

AEC 原理

Echo Cancellation

VoIP Echo Cancellation

Understanding the Echo "Phenomenon" Causes and Solutions

可適性濾波器演算法用於聲學回聲消除.pdf

speex AEC

Speex Acoustic Echo Cancellation (AEC) 回聲消除模塊的使用 2013

音訊演算法speex中的aec分析以及解析 2019

speexdsp回聲消除模塊在android中封裝及使用例子 2020

webetc AEC

單獨編譯和使用webrtc音訊回聲消除模組(附完整原始碼+測試音訊檔案)

WebRTC AudioProcessing 3A: AEC AGC ANC 初探

webrtc sample

WebRTC AudioProcessing 3A: AEC AGC ANC 初探

speex aec 與webrtc 回聲消除的比較優化