Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Acme.Sh
Commits
e22bcf7c
Commit
e22bcf7c
authored
Jun 17, 2016
by
neil
Committed by
GitHub
Jun 17, 2016
Browse files
support tls (#215)
* support tls-sni-01 '--tls' and '--tlsport' * fix tls doc
parent
869578ce
Changes
2
Show whitespace changes
Inline
Side-by-side
README.md
View file @
e22bcf7c
...
...
@@ -170,6 +170,20 @@ acme.sh --issue --standalone -d aa.com -d www.aa.com -d cp.aa.com
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# Use Standalone tls server to issue cert
**(requires you be root/sudoer, or you have permission to listen tcp 443 port)**
acme.sh supports
`tls-sni-01`
validation.
The tcp
`443`
port
**MUST**
be free to listen, otherwise you will be prompted to free the
`443`
port and try again.
```
bash
acme.sh
--issue
--tls
-d
aa.com
-d
www.aa.com
-d
cp.aa.com
```
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# Use Apache mode
**(requires you be root/sudoer, since it is required to interact with apache server)**
...
...
acme.sh
View file @
e22bcf7c
#!/usr/bin/env sh
VER
=
2.2.
6
VER
=
2.2.
7
PROJECT_NAME
=
"acme.sh"
...
...
@@ -17,6 +17,10 @@ STAGE_CA="https://acme-staging.api.letsencrypt.org"
VTYPE_HTTP
=
"http-01"
VTYPE_DNS
=
"dns-01"
VTYPE_TLS
=
"tls-sni-01"
VTYPE_TLS2
=
"tls-sni-02"
W_TLS
=
"tls"
BEGIN_CSR
=
"-----BEGIN CERTIFICATE REQUEST-----"
END_CSR
=
"-----END CERTIFICATE REQUEST-----"
...
...
@@ -251,7 +255,7 @@ _dbase64() {
fi
}
#Usage: hashalg
#Usage: hashalg
[outputhex]
#Output Base64-encoded digest
_digest
()
{
alg
=
"
$1
"
...
...
@@ -260,8 +264,14 @@ _digest() {
return
1
fi
outputhex
=
"
$2
"
if
[
"
$alg
"
=
"sha256"
]
;
then
if
[
"
$outputhex
"
]
;
then
echo
$(
openssl dgst
-sha256
-hex
|
cut
-d
=
-f
2
)
else
openssl dgst
-sha256
-binary
| _base64
fi
else
_err
"
$alg
is not supported yet"
return
1
...
...
@@ -288,6 +298,86 @@ _sign() {
}
# _createkey 2048|ec-256 file
_createkey
()
{
length
=
"
$1
"
f
=
"
$2
"
isec
=
""
if
_startswith
"
$length
"
"ec-"
;
then
isec
=
"1"
length
=
$(
printf
$length
|
cut
-d
'-'
-f
2-100
)
eccname
=
"
$length
"
fi
if
[
-z
"
$length
"
]
;
then
if
[
"
$isec
"
]
;
then
length
=
256
else
length
=
2048
fi
fi
_info
"Use length
$length
"
if
[
"
$isec
"
]
;
then
if
[
"
$length
"
=
"256"
]
;
then
eccname
=
"prime256v1"
fi
if
[
"
$length
"
=
"384"
]
;
then
eccname
=
"secp384r1"
fi
if
[
"
$length
"
=
"521"
]
;
then
eccname
=
"secp521r1"
fi
_info
"Using ec name:
$eccname
"
fi
#generate account key
if
[
"
$isec
"
]
;
then
openssl ecparam
-name
$eccname
-genkey
2>/dev/null
>
"
$f
"
else
openssl genrsa
$length
2>/dev/null
>
"
$f
"
fi
}
#_createcsr cn san_list keyfile csrfile conf
_createcsr
()
{
_debug _createcsr
domain
=
"
$1
"
domainlist
=
"
$2
"
key
=
"
$3
"
csr
=
"
$4
"
csrconf
=
"
$5
"
_debug2 domain
"
$domain
"
_debug2 domainlist
"
$domainlist
"
if
[
-z
"
$domainlist
"
]
||
[
"
$domainlist
"
=
"no"
]
;
then
#single domain
_info
"Single domain"
"
$domain
"
printf
"[ req_distinguished_name ]
\n
[ req ]
\n
distinguished_name = req_distinguished_name
\n
"
>
"
$csrconf
"
openssl req
-new
-sha256
-key
"
$key
"
-subj
"/CN=
$domain
"
-config
"
$csrconf
"
-out
"
$csr
"
else
if
_contains
"
$domainlist
"
","
;
then
alt
=
"DNS:
$(
echo
$domainlist
|
sed
"s/,/,DNS:/g"
)
"
else
alt
=
"DNS:
$domainlist
"
fi
#multi
_info
"Multi domain"
"
$alt
"
printf
"[ req_distinguished_name ]
\n
[ req ]
\n
distinguished_name = req_distinguished_name
\n
req_extensions = v3_req
\n
[ v3_req ]
\n
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
\n
subjectAltName=
$alt
"
>
"
$csrconf
"
openssl req
-new
-sha256
-key
"
$key
"
-subj
"/CN=
$domain
"
-config
"
$csrconf
"
-out
"
$csr
"
fi
}
#_signcsr key csr conf cert
_signcsr
()
{
key
=
"
$1
"
csr
=
"
$2
"
conf
=
"
$3
"
cert
=
"
$4
"
openssl x509
-req
-days
365
-in
"
$csr
"
-signkey
"
$key
"
-extensions
v3_req
-extfile
"
$conf
"
-out
"
$cert
"
}
_ss
()
{
_port
=
"
$1
"
...
...
@@ -364,7 +454,7 @@ createAccountKey() {
return
else
#generate account key
openssl genrsa
$length
2>/dev/null
>
"
$ACCOUNT_KEY_PATH
"
_createkey
$length
"
$ACCOUNT_KEY_PATH
"
fi
}
...
...
@@ -378,45 +468,12 @@ createDomainKey() {
fi
domain
=
$1
length
=
$2
isec
=
""
if
_startswith
"
$length
"
"ec-"
;
then
isec
=
"1"
length
=
$(
printf
$length
|
cut
-d
'-'
-f
2-100
)
eccname
=
"
$length
"
fi
if
[
-z
"
$length
"
]
;
then
if
[
"
$isec
"
]
;
then
length
=
256
else
length
=
2048
fi
fi
_info
"Use length
$length
"
if
[
"
$isec
"
]
;
then
if
[
"
$length
"
=
"256"
]
;
then
eccname
=
"prime256v1"
fi
if
[
"
$length
"
=
"384"
]
;
then
eccname
=
"secp384r1"
fi
if
[
"
$length
"
=
"521"
]
;
then
eccname
=
"secp521r1"
fi
_info
"Using ec name:
$eccname
"
fi
_initpath
$domain
length
=
$2
if
[
!
-f
"
$CERT_KEY_PATH
"
]
||
(
[
"
$FORCE
"
]
&&
!
[
"
$IS_RENEW
"
]
)
;
then
#generate account key
if
[
"
$isec
"
]
;
then
openssl ecparam
-name
$eccname
-genkey
2>/dev/null
>
"
$CERT_KEY_PATH
"
else
openssl genrsa
$length
2>/dev/null
>
"
$CERT_KEY_PATH
"
fi
_createkey
"
$length
"
"
$CERT_KEY_PATH
"
else
if
[
"
$IS_RENEW
"
]
;
then
_info
"Domain key exists, skip"
...
...
@@ -447,18 +504,7 @@ createCSR() {
return
fi
if
[
-z
"
$domainlist
"
]
||
[
"
$domainlist
"
=
"no"
]
;
then
#single domain
_info
"Single domain"
"
$domain
"
printf
"[ req_distinguished_name ]
\n
[ req ]
\n
distinguished_name = req_distinguished_name
\n
"
>
"
$DOMAIN_SSL_CONF
"
openssl req
-new
-sha256
-key
"
$CERT_KEY_PATH
"
-subj
"/CN=
$domain
"
-config
"
$DOMAIN_SSL_CONF
"
-out
"
$CSR_PATH
"
else
alt
=
"DNS:
$(
echo
$domainlist
|
sed
"s/,/,DNS:/g"
)
"
#multi
_info
"Multi domain"
"
$alt
"
printf
"[ req_distinguished_name ]
\n
[ req ]
\n
distinguished_name = req_distinguished_name
\n
[SAN]
\n
subjectAltName=
$alt
"
>
"
$DOMAIN_SSL_CONF
"
openssl req
-new
-sha256
-key
"
$CERT_KEY_PATH
"
-subj
"/CN=
$domain
"
-reqexts
SAN
-config
"
$DOMAIN_SSL_CONF
"
-out
"
$CSR_PATH
"
fi
_createcsr
"
$domain
"
"
$domainlist
"
"
$CERT_KEY_PATH
"
"
$CSR_PATH
"
"
$DOMAIN_SSL_CONF
"
}
...
...
@@ -821,9 +867,52 @@ _stopserver(){
fi
_get
"http://localhost:
$Le_HTTPPort
"
>
/dev/null 2>&1
_get
"http://localhost:
$Le_TLSPort
"
>
/dev/null 2>&1
}
# _starttlsserver san_a san_b port content
_starttlsserver
()
{
_info
"Starting tls server."
san_a
=
"
$1
"
san_b
=
"
$2
"
port
=
"
$3
"
content
=
"
$4
"
_debug san_a
"
$san_a
"
_debug san_b
"
$san_b
"
_debug port
"
$port
"
#create key TLS_KEY
if
!
_createkey
"2048"
"
$TLS_KEY
"
;
then
_err
"Create tls validation key error."
return
1
fi
#create csr
alt
=
"
$san_a
"
if
[
"
$san_b
"
]
;
then
alt
=
"
$alt
,
$san_b
"
fi
if
!
_createcsr
"tls.acme.sh"
"
$alt
"
"
$TLS_KEY
"
"
$TLS_CSR
"
"
$TLS_CONF
"
;
then
_err
"Create tls validation csr error."
return
1
fi
#self signed
if
!
_signcsr
"
$TLS_KEY
"
"
$TLS_CSR
"
"
$TLS_CONF
"
"
$TLS_CERT
"
;
then
_err
"Create tls validation cert error."
return
1
fi
#start openssl
(
printf
"HTTP/1.1 200 OK
\r\n\r\n
$content
"
| openssl s_server
-cert
"
$TLS_CERT
"
-key
"
$TLS_KEY
"
-accept
$port
>
/dev/null 2>&1
)
&
serverproc
=
"
$!
"
sleep
2
_debug serverproc
$serverproc
}
_initpath
()
{
if
[
-z
"
$LE_WORKING_DIR
"
]
;
then
...
...
@@ -935,6 +1024,20 @@ _initpath() {
if
[
-z
"
$CERT_PFX_PATH
"
]
;
then
CERT_PFX_PATH
=
"
$domainhome
/
$domain
.pfx"
fi
if
[
-z
"
$TLS_CONF
"
]
;
then
TLS_CONF
=
"
$domainhome
/tls.valdation.conf"
fi
if
[
-z
"
$TLS_CERT
"
]
;
then
TLS_CERT
=
"
$domainhome
/tls.valdation.cert"
fi
if
[
-z
"
$TLS_KEY
"
]
;
then
TLS_KEY
=
"
$domainhome
/tls.valdation.key"
fi
if
[
-z
"
$TLS_CSR
"
]
;
then
TLS_CSR
=
"
$domainhome
/tls.valdation.csr"
fi
}
...
...
@@ -1073,6 +1176,12 @@ _clearup() {
_stopserver
$serverproc
serverproc
=
""
_restoreApache
if
[
-z
"
$DEBUG
"
]
;
then
rm
-f
"
$TLS_CONF
"
rm
-f
"
$TLS_CERT
"
rm
-f
"
$TLS_KEY
"
rm
-f
"
$TLS_CSR
"
fi
}
# webroot removelevel tokenfile
...
...
@@ -1171,6 +1280,24 @@ issue() {
fi
fi
if
_hasfield
"
$Le_Webroot
"
"
$W_TLS
"
;
then
_info
"Standalone tls mode."
if
[
-z
"
$Le_TLSPort
"
]
;
then
Le_TLSPort
=
443
else
_savedomainconf
"Le_TLSPort"
"
$Le_TLSPort
"
fi
netprc
=
"
$(
_ss
"
$Le_TLSPort
"
|
grep
"
$Le_TLSPort
"
)
"
if
[
"
$netprc
"
]
;
then
_err
"
$netprc
"
_err
"tcp port
$Le_TLSPort
is already used by
$(
echo
"
$netprc
"
|
cut
-d
:
-f
4
)
"
_err
"Please stop it first"
return
1
fi
fi
if
_hasfield
"
$Le_Webroot
"
"apache"
;
then
if
!
_setApache
;
then
_err
"set up apache error. Report error to me."
...
...
@@ -1263,6 +1390,11 @@ issue() {
if
_startswith
"
$_currentRoot
"
"dns"
;
then
vtype
=
"
$VTYPE_DNS
"
fi
if
[
"
$_currentRoot
"
=
"
$W_TLS
"
]
;
then
vtype
=
"
$VTYPE_TLS
"
fi
_info
"Getting token for domain"
$d
if
!
_send_signed_request
"
$API
/acme/new-authz"
"{
\"
resource
\"
:
\"
new-authz
\"
,
\"
identifier
\"
: {
\"
type
\"
:
\"
dns
\"
,
\"
value
\"
:
\"
$d
\"
}}"
;
then
...
...
@@ -1406,7 +1538,7 @@ issue() {
_debug
"keyauthorization"
"
$keyauthorization
"
_debug
"uri"
"
$uri
"
removelevel
=
""
token
=
""
token
=
"
$(
printf
"%s"
"
$keyauthorization
"
|
cut
-d
'.'
-f
1
)
"
_debug
"_currentRoot"
"
$_currentRoot
"
...
...
@@ -1439,7 +1571,6 @@ issue() {
_debug wellknown_path
"
$wellknown_path
"
token
=
"
$(
printf
"%s"
"
$keyauthorization
"
|
cut
-d
'.'
-f
1
)
"
_debug
"writing token:
$token
to
$wellknown_path
/
$token
"
mkdir
-p
"
$wellknown_path
"
...
...
@@ -1451,6 +1582,37 @@ issue() {
fi
fi
elif
[
"
$vtype
"
=
"
$VTYPE_TLS
"
]
;
then
#create A
#_hash_A="$(printf "%s" $token | _digest "sha256" "hex" )"
#_debug2 _hash_A "$_hash_A"
#_x="$(echo $_hash_A | cut -c 1-32)"
#_debug2 _x "$_x"
#_y="$(echo $_hash_A | cut -c 33-64)"
#_debug2 _y "$_y"
#_SAN_A="$_x.$_y.token.acme.invalid"
#_debug2 _SAN_A "$_SAN_A"
#create B
_hash_B
=
"
$(
printf
"%s"
$keyauthorization
| _digest
"sha256"
"hex"
)
"
_debug2 _hash_B
"
$_hash_B
"
_x
=
"
$(
echo
$_hash_B
|
cut
-c
1-32
)
"
_debug2 _x
"
$_x
"
_y
=
"
$(
echo
$_hash_B
|
cut
-c
33-64
)
"
_debug2 _y
"
$_y
"
#_SAN_B="$_x.$_y.ka.acme.invalid"
_SAN_B
=
"
$_x
.
$_y
.acme.invalid"
_debug2 _SAN_B
"
$_SAN_B
"
if
!
_starttlsserver
"
$_SAN_B
"
"
$_SAN_A
"
"
$Le_TLSPort
"
"
$keyauthorization
"
;
then
_err
"Start tls server error."
_clearupwebbroot
"
$_currentRoot
"
"
$removelevel
"
"
$token
"
_clearup
return
1
fi
fi
if
!
_send_signed_request
$uri
"{
\"
resource
\"
:
\"
challenge
\"
,
\"
keyAuthorization
\"
:
\"
$keyauthorization
\"
}"
;
then
...
...
@@ -2203,6 +2365,7 @@ Parameters:
--webroot, -w /path/to/webroot Specifies the web root folder for web root mode.
--standalone Use standalone mode.
--tls Use standalone tls mode.
--apache Use apache mode.
--dns [dns_cf|dns_dp|dns_cx|/path/to/api/file] Use dns mode or dns api.
--dnssleep [60] The time in seconds to wait for all the txt records to take effect in dns api mode. Default 60 seconds.
...
...
@@ -2227,6 +2390,7 @@ Parameters:
--accountkey Specifies the account key path, Only valid for the '--install' command.
--days Specifies the days to renew the cert when using '--issue' command. The max value is 80 days.
--httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
--tlsport Specifies the standalone tls listening port. Only valid if the server is behind a reverse proxy or load balancer.
--listraw Only used for '--list' command, list the certs in raw format.
"
}
...
...
@@ -2277,6 +2441,7 @@ _process() {
_accountkey
=
""
_certhome
=
""
_httpport
=
""
_tlsport
=
""
_dnssleep
=
""
_listraw
=
""
while
[
${#}
-gt
0
]
;
do
...
...
@@ -2399,6 +2564,14 @@ _process() {
_webroot
=
"
$_webroot
,
$wvalue
"
fi
;;
--tls
)
wvalue
=
"
$W_TLS
"
if
[
-z
"
$_webroot
"
]
;
then
_webroot
=
"
$wvalue
"
else
_webroot
=
"
$_webroot
,
$wvalue
"
fi
;;
--dns
)
wvalue
=
"dns"
if
!
_startswith
"
$2
"
"-"
;
then
...
...
@@ -2490,6 +2663,12 @@ _process() {
Le_HTTPPort
=
"
$_httpport
"
shift
;;
--tlsport
)
_tlsport
=
"
$2
"
Le_TLSPort
=
"
$_tlsport
"
shift
;;
--listraw
)
_listraw
=
"raw"
;;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment