分類
网站

本站域名變更:從 wupo 到 shaman

首先感謝 EU.org 提供的 free 二級域名,本站從即日起開始在新域名 https://ft.shaman.eu.org 下更新,原 https://ft.wupo.info 會在一天後跳轉到本站。 https://emanon.wupo.info 由於停更,所以本次不會遷移到新域名,但是會在明年域名到期後下線。Emanon 有一個自然觀察的 Youtube 頻道,裡面都是些常見物種記錄。


本次遷移域名遇到的小問題

由於不是很緊迫,所以我是在同一個服務器上複製了一份數據庫,然後又複製了一份 wordpress 文件夾,最後再複製一份 nginx 的配置文件就搞定了。如果遇到 nginx 500 錯誤,記得檢查文件權限。需要在數據庫里操作的幾處我列一下:

#如果只是修改域名,則只需執行下面兩行
update options set option_value="https://ft.shaman.eu.org" where option_name="siteurl";
update options set option_value="https://ft.shaman.eu.org" where option_name="home";

#如果要修改用戶的電子郵箱
update users set user_email='[email protected]' where user_login='user1';
#如果要修改管理員的電子郵箱
update options set option_value='[email protected]' where option_name='admin_email';

還有一個問題是,配置 cloudflare 時出現循環 301 Moved Permanently 跳轉。原因是 cloudflare 默認的 SSL/TLS 設置是 Flexible,這種模式意味着用戶到 cloudflare 是 https,而 cloudflare 到我的服務器卻是 http。但是我的服務器也配置了如果是 http 就重定向到 https。於是就循環請求了。解決辦法是把 cloudflare的 SSL/TLS 設置為 Full (strict) 模式。

nginx 和 cloudflare 設置 301 跳轉都很簡單,這裡寫下用 cloudflare 設置跳轉的方法。在 Page Rule 中新建一條(免費用戶最多可以創建三條)Page Rule。URL matches 填「*ft.wupo.info/*」,接着的兩個下拉框分別選「Forwarding URL」和「301 - Permanent Redirect」,最後一個輸入框填「https://ft.shaman.eu.org/$2」。保存並啟用就可以了。

本文最早發布於 2020/11/03。

分類
网站

嘗試攔截來自 Cloudflare IP 的密碼猜解

我的 WordPress 安裝了 Limit Login Attempts 插件,其中可以設置輸入錯誤密碼 m 次封鎖這個 IP n 小時,並記錄下這個 IP。本站最近有很多來自 Cloudflare IP 的錯誤登錄嘗試,於是我試圖使用下面兩個方法攔截,可惜結果證明無效。於是我使用了 OTP (One-time password)來增加暴力破解的難度,直到再次找到可行的攔截方法。我還安裝了一個修改 WordPress 登錄頁網址的插件 WPS Hide Login,應該也能有些作用。

Cloudflare Firewall

免費 Cloudflare 用戶可以創建 5 個防火牆規則,我建立了如下兩條:

(http.host in {"ft.wupo.info"} and ip.geoip.asnum in {13335})
(ip.src in {173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/12 172.64.0.0/13 131.0.72.0/22} and http.host eq "ft.wupo.info")

我隨便查了幾個 Cloudflare IP 的 AS 編號都是 13335,所以第一條就是如果 IP 的 AS 編碼是 13335 就攔截。順便推薦個我經常用的查 IP 的網站 IP-API

第二條是根據 IP 地址來封鎖,從這裡獲得 Cloudflare 的 IP

(ip.geoip.country ne "KP" and http.host eq "ft.wupo.info")

如果想根據 IP 所在國家來限制訪問也是可以的,上面的便是限制了北韓以外 IP 的訪問本站。

在 Limit Login Attempts 插件中限制 IP

這個就是一行一個填已經攔截的 IP 就可以了,可以把所有 IP 複製下來,然後粘貼到 LibreOffice Calc 中,按需要進行排序後複製出 IP 列貼回插件中就可以了。

分類
网站

WordPress 使用 OTP 增強站點安全性

一次性密碼 (One-time password)又稱動態密碼或單次有效密碼,是指計算機系統或其他數位裝置上只能使用一次的密碼,有效期為只有一次登入會話或交易。OTP 避免了一些與傳統基於密碼認證相關聯的缺點;一些實作還納入了雙因素認證,確保單次有效密碼需要存取一個人有的某件事物以及一個人知道的某件事物。——維基百科

本站使用的開源 OTP 插件是 WP-OTP。安裝啟用後在「使用者」>「個人資料」頁面,會有二維碼出現,用自己喜歡的 OTP 客戶端掃描後輸入生成的密碼就開啟了網站的 OTP 登錄。

我使用的 OTP 軟件是開源的 andOTP。安裝後會提示給 andOTP 客戶端自己設置個密碼,以保護動態密碼的安全。設置好後點擊主界面右下角的「+」,掃描 WordPress 個人資料頁的二維碼,將出現的數字填入 WordPress 後台就完成了所有的設置。

平常使用的場景是:打開 WordPress 的登錄頁,輸入賬號密碼。打開手機上的 andOTP 查看當前的動態密碼( 6 位數字)。將動態密碼也輸入登錄頁,完成登錄。

分類
网站

未備案域名被拒絕解析緊急處理

未備案域名的80端口被停止解析,業務被中段。緊急將域名指向香港服務器,並在香港服務器nginx做如下轉發即可:

server {
    server_name manage.wupo.info;
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://1.2.3.4:8888;
    }
    access_log logs/manage.wupo.info_access.log;
}

如果目標地址仍是80,需要注釋掉proxy_set_header Host $host;這句,否則還是訪問不了。

分類
网站

nginx記錄特定請求的日誌

通過nginx的access log可以記錄訪問日誌,如果只想記錄特定的某條請求,例如所有以/get開頭的請求,可以這麼配置:

map $request $loggable {
    ~/get* 1;
    default 0;
}

server {
        listen 8085;
        server_name 127.0.0.1;
        charset utf-8;

        access_log logs/flask.access.log combined if=$loggable;
        location /  { try_files $uri @yourapplication; }
        location @yourapplication {
                include uwsgi_params;
                uwsgi_pass 127.0.0.1:3031;
        }
}

如果要排除,只記錄以/get開頭的請求,map可以這麼寫

map $request $loggable {
    ~/get* 0;
    default 1;
}

修改之後可以通過 tail -f ../logs/flask.access.log實時查看log的變動。

分類
网站

黑屏

我的這塊戴爾S2340Mc屏,黑色時完全就是一面鏡子!為了當鏡子用,我需要一塊黑色。另外div中height設1000%是不行,參考height: 100% not working

浮動無邊黑屏

#!/usr/bin/python3
# -*- coding: utf8 -*-

#dnf install python3-matplotlib
#pip install matplotlib,fire

#指定起始坐標xy、寬度、高度和顏色,來畫一個填充好的矩形
#為了遮擋盜版電影頂部和底部的賭城廣告

import fire,matplotlib

def drawRectangle(x='0',y='0',width='400',length='400',color='black'):
    #"640x400+0+200"
    conf = str(width) + 'x' + str(length) + '+' + str(x) + '+' + str(y)
    # make sure Tk backend is used
    matplotlib.use("TkAgg")  
    import matplotlib.pyplot as plt
    # turn navigation toolbar off
    plt.rcParams['toolbar'] = 'None'
    plt.rcParams['figure.facecolor'] = color
    # create a figure and subplot
    fig, ax = plt.subplots(figsize=(2,2))
    #remove margins
    fig.subplots_adjust(0,0,1,1)
    # turn axes off
    ax.axis("off")
    # show image
    # im = plt.imread("black.png")
    # ax.imshow(im)
    
    # remove window frame
    fig.canvas.manager.window.overrideredirect(1)
    plt.get_current_fig_manager().window.wm_geometry(conf)
    plt.show()
    
#drawRectangle('10','980')

if __name__ == '__main__':
    fire.Fire(drawRectangle)
    
#默認在屏幕左上角生成一個400*400的黑屏
python drawRectangle.py
#在左下角(0,980)生成一個128*72的紅屏
python drawRectangle.py 0 980 128 72 red

本文最早發布於 2017/03/08。

分類
网站

日期時間選擇器

使用bootstrap-datetimepicker來做出日期時間選擇器

<!DOCTYPE html>
<htmllang="zh-CN">
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="../js/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="../js/bootstrap-datetimepicker.js" charset="UTF-8"></script>
<script type="text/javascript" src="../js/locales/bootstrap-datetimepicker.zh-CN.js" charset="UTF-8"></script>
<script type="text/javascript" src="./Chart.bundle.min.js"></script>
<link href="./bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
<link href="../css/bootstrap-datetimepicker.min.css" rel="stylesheet" media="screen">

</head>
<body>
<br/>
<div class="container">
  <div>
    <form action="" class="form-inline"  role="form">
		  <div class="col-sm-12 col-md-2">
            <select name='appleIDOption' id='appleIDOption' class="form-control" >
            <!-- <option value="volvo">Volvo</option>  -->
            </select>     
        </div>   

        <div class="form-group col-sm-12 col-md-9">
            <label for="dtp_input1" class="col-md-2 control-label">开始时间</label>
            <div id="startTime" class="input-group date form_datetime col-md-4" data-date="" data-date-format="yyyy-mm-dd hh:ii" data-link-field="dtp_input1">
                <input class="form-control" size="16" type="text" value="" readonly>
                <span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
				<span class="input-group-addon"><span class="glyphicon glyphicon-th"></span></span>
            </div>
			<input type="hidden" id="dtp_input1" data-date-format="yyyy-mm-ddThh:ii:ss" value="" />


            <label for="dtp_input2" class="col-md-2 control-label">结束时间</label>
            <div id="endTime" class="input-group date form_datetime col-md-4" data-date="" data-date-format="yyyy-mm-dd hh:ii" data-link-field="dtp_input2">
                <input class="form-control" size="16" type="text" value="" readonly>
                <span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
				<span class="input-group-addon"><span class="glyphicon glyphicon-th"></span></span>
            </div>
			<input type="hidden" id="dtp_input2" data-date-format="yyyy-mm-ddThh:ii:ss" value="" /><br/>
        </div>		
    </form>	
		  <div class="col-sm-12 col-md-1">
          <button class="btn btn-default" id="query">查询</button>
        </div>
  </div>
</div>

<div id="charts" class="container" style="max-width:1600px;max-height:400px;"></div>

</body>
<script type="text/javascript">
    $('.form_datetime').datetimepicker({
        language:  'zh-CN',
        weekStart: 1,
        todayBtn:  1,
        autoclose: 1,
        todayHighlight: 1,
        startView: 2,
        forceParse: 0
    });

//沒有找到bootstrap-datetimepicker中轉出時間戳的格式,只好自己轉
//datastring後面不加+08:00的話Chrome會用+00:00,導致時間戳有誤
    $('#startTime').datetimepicker().on('hide', function(ev){
        $('#dtp_input1').val(Date.parse($('#dtp_input1').val().replace(' ',"T") + "+08:00"));
    });
    $('#endTime').datetimepicker().on('hide', function(ev){
        $('#dtp_input2').val(Date.parse($('#dtp_input2').val().replace(' ',"T") + "+08:00"));
    });

  $("#query").click(function(){
	    $( "#charts" ).empty();
	    var appleIDSelected = $('#appleIDOption').val();
//	    只取十位就好了
	    var startTime = $('#dtp_input1').val().substr(0,10);
	    var endTime = $('#dtp_input2').val().substr(0,10);
	    var postData = { appleID: appleIDSelected,startTime: startTime,endTime: endTime };
	    var jsonData = $.ajax({
		    url: 'keywordData.php',
		    method: 'POST',
		    data: postData,
		  }).done(function (results) {
//			  prepareChart(results);
		    });
	  });
</script>
</html>