Tag Archives

8 Articles

lua-resty-acme: ACMEv2客戶端和Let’s Encrypt證書的自動化管理

0   10697 轉為簡體

 

 

安裝

使用opm:

opm中沒有luaossl庫,所以這種安裝使用的是基於FFI的Openssl後端;需要OpenResty鏈接了大於等於1.1版本的OpenSSL。

也可以使用luarocks安裝:

使用

以/etc/openresty目錄為例,如果目錄不存在,請自行修改。

生成一個賬戶密鑰

生成一個默認證書

在Nginx配置的http 節插入以下內容

首次配置時,建議將init_by_lua_block中的staing = true取消注釋,以防錯誤過多觸發限流;測試通過後再加回注釋使用生產API。

在需要使用證書的server節插入

CentOS/Fedora等系統的根證書在/etc/ssl/certs/ca-bundle.crt,請根據實際情況修改lua_ssl_trusted_certificate。

保存後,reload nginx。

在一般情況下,domain_whitelist必須配置,以防止惡意請求通過偽造SNI頭進行拒絕服務攻擊。

如果要匹配一系列域名,可以使用__index來實現。比如下面的例子僅匹配example.com的子域名:

RSA+ECC雙證書

將init_by_lua_block中的domain_key_types = { 'rsa', 'ecc' }取消注釋後,即可同時申請兩套證書。

為了讓申請到證書前的握手不出錯斷開,給Nginx配置默認的ECC證書

然後在server節中原有的ssl_certificate下增加兩行

關於加密套件等的選擇可藉助搜索引擎。

TLS-ALPN-01

0.5.0開始支持tls-alpn-01,可以支持在只開放443埠的環境里完成驗證。方法是通過蜜汁FFI偏移找到當前請求的SSL結構,然後設置了新的ALPN。需要多個stream server多次proxy,拓撲結構如下:

第一個stream server打開了443埠,根據請求的ALPN分發到不同的後段;如果是acme-tls則轉發到我們的庫,否則轉發到正常的https。

示例配置見Github

lua-resty-multiplexer: 埠服務復用

0   10142 轉為簡體

實現了一個埠服務復用的透明代理,可以在同一個埠上運行多個協議。根據每次連接中客戶端發起的首個請求檢測協議,根據協議或各種條件選擇代理的上游。

需要打一個補丁。由@fcicq這個討論中貢獻。這個補丁實現了BSD的socket recv()語義。目前官方也有這個feature的PR

示例配置:

示例中服務監聽在80埠,並定義規則:

  • 如果客戶端來自 10.0.0.1,代理到 internal-host.com:80
  • 如果請求協議是HTTP 而且客戶端來自10.0.0.2,代理到 internal-host:8001
  • 如果請求協議是 SSH,代理到 github.com:22
  • 如果請求協議是 DNS,代理到 1.1.1.1:53
  • 如果請求協議是 SSL/TLS 而且現在的時間是 0 到 30分,代理到 twitter.com:443
  • 如果請求協議是 SSL/TLS 而且現在的時間是 31 到 59分,代理到  www.google.com:443
  • 以上均不滿足,代理到 127.0.0.1:80

說明

  • 只能實現識別連接建立後客戶端先發送請求的協議,不兼容服務端先發送響應的協議(比如FTP,SMTP等)
  • 如果實現了ngx.reqsock.peak(),則可以使用ngx_stream_proxy來轉發流量,這樣的話除了首個請求以外同一連接的後續請求將沒有額外的性能損失;目前只能在Lua層轉發。

Read More

使用Redis協議來調試ngx.shared

0   8990 轉為簡體

有時候用ngx.shared的時候想看一下到底存進去的值是什麼,或者想列一下滿足條件的鍵,或者想批量操作,所以這個項目就是用來解決這個問題的。

除了支持ngx.shared提供的操作以外,學習Redis增加了PING(測試連通性),KEYS(列出符合條件的鍵)和EVAL(在伺服器上執行Lua腳本)。

已上傳到opm,可以通過

opm install fffonion/lua-resty-shdict-server

一鍵安裝。

由於目前stream和http子系統是兩個獨立的Lua VM,因此不能通過全局變數來共享數據。另外兩個子系統的shdict是分別定義的,因此也不能互擼。所以如果想用這個模塊來在redis-cli里擼http子系統下定義的shdict,需要這個補丁

示例配置:

然後

 

使用lua-nginx-module緩存JSONP

0   10757 轉為簡體

最近給暢言加上了單點登錄,也就是可以用網站的帳號來在暢言上發射評論。暢言會通過你設置的一個介面來獲得用戶名,頭像等。但是我發現隊友暢言會頻繁請求這個介面,有時候會達到單個用戶一秒鐘好幾次??

雖然在php層有redis,壓力不會很大,但是這樣頻繁的請求還是會中防CC的策略,影響用戶正常的瀏覽。所以我決定在CDN上做個緩存。

Read More

cidr.me地理位置查詢

2   14642 轉為簡體

基於OpenResty ,MaxMind GeoIP資料庫和從bgp.he.net生成的ASN資料庫,因為沒有經緯度的需求所以沒有顯示。下文有源代碼的鏈接,如果需要可以自行修改加上經緯度或者將輸出變為JSON等。

這裡有chrome插件

使用方法

查詢當前IPv4地址

$ curl http://cidr.me/ip
x.x.x.x

查詢當前IPv6地址

$ curl http://ipv6.cidr.me/ip
x.x.x.x

查詢當前IP的PTR記錄(反向DNS),地理位置和ASN

$ curl http://cidr.me/
x.x.x.x
Country, City
ASN number

查詢當前IP的PTR記錄

$ curl http://cidr.me/rdns
x-x-x-x.com

查詢指定IP的地理位置

$ curl http://cidr.me/74.125.203.199
74.125.203.199 th-in-f199.1e100.net
United States, California, Mountain View
AS15169 Google Inc.

查詢域名的地理位置

$ curl http://cidr.me/www.google.com.hk
172.217.3.195 sea15s12-in-f3.1e100.net
United States, California, Mountain View
AS15169 Google LLC

2607:f8b0:400a:809::2003 sea15s12-in-x03.1e100.net
United States
AS15169 Google LLC

查詢域名的IP

$ curl http://cidr.me/www.google.com.hk/ip
74.125.203.199
2607:f8b0:400a:809::2003

查詢域名的IP和CNAME(如果存在)

$ curl http://cidr.me/www.youtube.com/dns
youtube-ui.l.google.com 172.217.3.174
172.217.3.206
216.58.193.78
216.58.217.46
2607:f8b0:400a:808::200e

源代碼

在這裡https://gist.github.com/fffonion/44e5fb59e2a8f0efba5c1965c6043584

需要ngx_http_geoip_module, echo-nginx-module, lua-nginx-module,安裝libgeoip,並將maxmind的舊版geoip資料庫放在/usr/share/GeoIP

通過bgp.he.net生成ASN資料庫

Read More

用 OpenResty 寫了一個 SNI 代理

0   12463 轉為簡體

功能類似於dlundquist/sniproxy

推薦 OpenResty 加上 stream 模塊和 ngx_stream_lua_module 模塊。在 1.9.15.1 上測試通過。

示例配置:

A Lua table sni_rules should be defined in the init_worker_by_lua_block directive.

The key can be either whole host name or regular expression. Use . for a default host name. If no entry is matched, connection will be closed.

The value is a table containing host name and port. If host is set to nil, the server_name in SNI will be used. If the port is not defined or set to nil, 443 will be used.

Rules are applied with the priority as its occurrence sequence in the table. In the example above, twitter.com will match the third rule rather than the fourth.

If the protocol version is less than TLSv1 (eg. SSLv3, SSLv2), connection will be closed, since SNI extension is not supported in these versions.