mod_secure_link
Introduction
mod_secure_link is used to check authenticity of requested links, protect resources from unauthorized access, and limit link lifetime.
Module Configuration
Description
the basic config in: conf/mod_secure_link/mod_secure_link.conf
Config Item | Description |
---|---|
Basic.DataPath | String Path of rule configuration |
Log.OpenDebug | Boolean Debug flag of module |
Example
[Basic]
DataPath = ./mod_secure_link/secure_link.data
[Log]
OpenDebug = true
Rule Configuration
Description
conf/mod_secure_link/secure_link_rule.data
Config Item | Description |
---|---|
Version | String Version of config file |
Config | Object Rules for each product |
Config{k} | String Product name |
Config{v} | Object A list of rules |
Config{v}[].Cond | String Condition expression, See Condition |
Config[v][].ChecksumKey | String The key which stored Checksum Value in Query |
Config[v][].ExpiresKey | String The key which stored Expired time in Query |
Config[v][].ExpressionNodes | Array Nodes which join calculate Checksum |
Config[v][].ExpressionNodes[].Type | String Node Type, see Node Type to get more information |
Config[v][].ExpressionNodes[].Param | String The param may be used to get Final Value |
Node Type
be supported node type and Calculate logic:
type | Calculate logic |
---|---|
label | $Param |
query | req.URL.Query($Param) |
header | req.Header.Get($Param) |
host | req.Host |
uri | req.RequestURI |
remote_addr | req.RemoteAddr |
Example
{
"Version": "2019-12-10184356",
"Config": {
"p1": [{
"Cond": "default_t()",
"ChecksumKey": "sign",
"ExpiresKey": "time",
"ExpressionNodes": [{
"Type": "query",
"Param": "time"
},
{
"Type": "uri"
},
{
"Type": "remote_addr"
},
{
"Type": "label",
"Param": " secret"
}
]
}]
}
}
Link generate logic
With above config, the pseudo code to generate link is:
func WrapSecureLinkParam (req *http.Request) {
now := time.Now().Unix()
expires := now + int64(time.Hour*24/time.Second)
// step1: get origin data
origin := fmt.Sprintf("%d%s%s%s", expires, req.RequestURI, req.RemoteAddr, " secret")
// step2: generator sign
sign := func(origin string) string {
tmpB := md5.Sum([]byte(origin))
tmp := base64.StdEncoding.EncodeToString(tmpB[:])
tmp = strings.ReplaceAll(tmp, "+", "-")
tmp = strings.ReplaceAll(tmp, "/", "_")
tmp = strings.ReplaceAll(tmp, "=", "")
return tmp
}
// step3: generate link
req.URL.Query().Set("sign", sign(origin))
req.URL.Query().Set("time", fmt.Sprintf("%d", expires))
}
step2: the sign logic in shell is:
echo -n $origin | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =
// one example:
echo -n '2147483647/s/link127.0.0.1 secret' | openssl md5 -binary | openssl base64 | tr +/ -_ | tr -d =
_e4Nc3iduzkWRm01TBBNYw