Compare commits

...
Sign in to create a new pull request.

25 commits

Author SHA1 Message Date
d6ac9af1c3
chore: go 1.24 and regen go.mod 2025-02-24 16:03:51 -08:00
ddvk
1b0cb6d5c1 add dev cloud urls 2024-12-15 15:33:18 +01:00
ddvk
665318f08b
Update README.md
typo
2024-11-23 09:04:14 +01:00
ddvk
d41cf0b79f
Update README.md
add simple instructions for rmpro
2024-11-23 09:02:57 +01:00
ddvk
8fc87780f1
Merge pull request #15 from ddvk/revert-14-add-apphost-com
Revert "Add host local.apphost.com"
2024-11-15 18:06:50 +01:00
ddvk
01ed34dc5e
Revert "Add host local.apphost.com" 2024-11-15 18:06:01 +01:00
ddvk
ce61af629c
Merge pull request #14 from innerand/add-apphost-com 2024-11-14 08:27:29 +01:00
Andreas Innerlohninger
1edf5ea4a9 Add host local.apphost.com 2024-11-10 16:04:10 +01:00
ddvk
45f7f5eff6
Merge pull request #13 from Esras/feature/add_rmpro_build_and_installer
Add RM Paper Pro Support
2024-10-07 18:22:51 +02:00
ddvk
ad06c390bb fix build 2024-10-07 14:05:44 +02:00
Esras
e5dec23cd6 Add back in original INSTALLER target for backwards compatability. 2024-10-05 17:24:34 -07:00
Esras
eb3d963a87 Add a new target for the RMPro installer to the Makefile and rearrange / rename some of the other variables to reflect multiple outputs. 2024-10-05 17:14:57 -07:00
ddvk
743a38c344 rename binary to rmfakecloud-proxy 2024-09-26 20:54:33 +02:00
Dobrin von Känel
3ddeb5ae39
Merge pull request #9 from Eeems/patch-1 2023-11-29 10:21:35 +01:00
Nathaniel van Diepen
2f208b01d6
Don't run sed if no metadata files are found 2023-11-28 16:45:06 -07:00
ddvk
fbd6f6f16a add new localhost address 2022-10-28 23:41:02 +02:00
ddvk
fce8ddfeb2 add more hosts 2022-04-06 21:18:56 +02:00
Dobrin von Känel
b137c369b0
Update README.md 2021-12-14 11:13:49 +01:00
ddvk
3c2bac1b29 add doc for config 2021-09-27 00:26:42 +02:00
ddvk
a6a59b1c3a tidy installer script 2021-09-27 00:09:46 +02:00
ddvk
83feb65863
Merge pull request #2 from matteodelabre/rewrite-host-header
Rewrite the Host header in forwarded requests
2021-09-26 22:38:44 +02:00
Mattéo Delabre
9ef79c874c
Rewrite the Host header in forwarded requests
The default httputil.NewSingleHostReverseProxy implementation does not rewrite the Host header in forwarded requests. So, the upstream server receives requests with the Host header set as the original reMarkable domain. In where a reverse proxy is used in front of rmfakecloud (as suggested [here](https://github.com/ddvk/rmfakecloud/blob/master/docs/https.md)), this can make the HTTP server confused especially if it is configured to serve several websites (in which case the Host header is used to differentiate requests).

This PR replaces the call to NewSingleHostReverseProxy with an implementation that rewrites the Host header (by assigning `req.Host`). This is essentially a copy/paste of the [original implementation](https://cs.opensource.google/go/go/+/refs/tags/go1.17.1:src/net/http/httputil/reverseproxy.go;drc=b7a85e0003cedb1b48a1fd3ae5b746ec6330102e;l=143) but with a new line added that does the rewrite. I don’t know if there’s a cleaner way to do this, and this may introduce licensing issues since the original source is BSD-licensed.
2021-09-26 19:43:03 +02:00
ddvk
65969a4697 add yaml 2021-03-21 10:26:56 +01:00
ddvk
8e3defba48 add more hosts 2021-03-21 10:18:07 +01:00
ddvk
8b07f20657
Merge pull request #1 from ddvk/add-license-1
Create LICENSE
2021-02-12 17:30:53 +01:00
8 changed files with 243 additions and 72 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
version.go
dist/

2
.mise.toml Normal file
View file

@ -0,0 +1,2 @@
[tools]
golang = "1.24.0"

View file

@ -1,16 +1,37 @@
BINARY=dist/rmake-proxy
ARMV7_BINARY=dist/rmfakecloud-proxy-arm7
AARCH64_BINARY=dist/rmfakecloud-proxy-aarch64
WIN_BINARY=dist/rmfakecloud-proxy.exe
LINUX_BINARY=dist/rmfakecloud-proxy64
INSTALLER=dist/installer.sh
RM12_INSTALLER=dist/installer-rm12.sh
RMPRO_INSTALLER=dist/installer-rmpro.sh
.PHONY: clean
all: $(INSTALLER)
all: $(RMPRO_INSTALLER) $(RM12_INSTALLER) $(INSTALLER) $(WIN_BINARY) $(LINUX_BINARY)
$(BINARY): version.go
GOARCH=arm GOARM=7 go build -ldflags="-w -s" -o $(BINARY)
version.go:
$(LINUX_BINARY): version.go main.go
go build -ldflags="-w -s" -o $@
$(ARMV7_BINARY): version.go main.go
GOARCH=arm GOARM=7 go build -ldflags="-w -s" -o $@
$(AARCH64_BINARY): version.go main.go
GOARCH=arm64 go build -ldflags="-w -s" -o $@
$(WIN_BINARY): version.go main.go
GOOS=windows go build -ldflags="-w -s" -o $@
version.go:
go generate
$(INSTALLER): $(BINARY) scripts/installer.sh
$(RMPRO_INSTALLER): $(AARCH64_BINARY) scripts/installer.sh
cp scripts/installer.sh $@
gzip -c $(BINARY) >> $@
gzip -c $(AARCH64_BINARY) >> $@
chmod +x $@
$(INSTALLER) $(RM12_INSTALLER): $(ARMV7_BINARY) scripts/installer.sh
cp scripts/installer.sh $@
gzip -c $(ARMV7_BINARY) >> $@
chmod +x $@
clean:
rm -fr dist

View file

@ -3,22 +3,54 @@ Single-minded HTTPS reverse proxy
(forked from https://github.com/yi-jiayu/secure)
## Installation
### Manual
Download `installer-rm12.sh` for rm1/2 or `installer-rmpro.sh` on a pc.
Transfer to the tablet with `scp` / `WinSCP`
run installer on the tablet over ssh
```
chmod +x installer-xxx.sh
./installer-xxx.sh
```
### Use toltec if supported
`opkg install rmfakecloud-proxy`
### rmpro
To make it permanent, make root writable and unmount /etc first e.g.
```
mount -o remount,rw /
umount -R /etc
./installer-rmpro.sh
```
## Usage
```
usage: secure [-addr host:port] -cert certfile -key keyfile upstream
usage: rmfakecloud-proxy [-addr host:port] -cert certfile -key keyfile upstream
-addr string
listen address (default ":443")
-cert string
path to cert file
-key string
path to key file
-c configfile
upstream string
upstream url
```
### Example
```
secure -cert cert.pem -key key.pem http://localhost:6060
rmfakecloud-proxy -cert cert.pem -key key.pem http://localhost:6060
```
## Configfile
```yaml
cert: proxy.crt
key: proxy.key
upstream: https://somehost:123
#addr: :443
```

4
go.mod
View file

@ -1,3 +1,5 @@
module github.com/yi-jiayu/secure
go 1.15
go 1.24
require gopkg.in/yaml.v3 v3.0.1

4
go.sum Normal file
View file

@ -0,0 +1,4 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

125
main.go
View file

@ -14,33 +14,40 @@ import (
"os"
"os/signal"
"path/filepath"
"strconv"
"strings"
"syscall"
"gopkg.in/yaml.v3"
)
type Config struct {
CertFile string `yaml:"cert"`
KeyFile string `yaml:"key"`
Upstream string `yaml:"upstream"`
Addr string `yaml:"addr"`
}
var (
certFile string
keyFile string
upstream string
addr string
version bool
version bool
configFile string
)
func init() {
flag.StringVar(&addr, "addr", ":443", "listen address")
flag.StringVar(&certFile, "cert", "", "path to cert file")
flag.StringVar(&keyFile, "key", "", "path to key file")
func getConfig() (config *Config, err error) {
cfg := Config{}
flag.StringVar(&configFile, "c", "", "config file")
flag.StringVar(&cfg.Addr, "addr", ":443", "listen address")
flag.StringVar(&cfg.CertFile, "cert", "", "path to cert file")
flag.StringVar(&cfg.KeyFile, "key", "", "path to key file")
flag.BoolVar(&version, "version", false, "print version string and exit")
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(),
"usage: %s [-addr host:port] -cert certfile -key keyfile [-version] upstream\n",
"usage: %s -c [config.yml] [-addr host:port] -cert certfile -key keyfile [-version] upstream\n",
filepath.Base(os.Args[0]))
flag.PrintDefaults()
fmt.Fprintln(flag.CommandLine.Output(), " upstream string\n \tupstream url")
}
}
func _main() error {
flag.Parse()
if version {
@ -48,22 +55,100 @@ func _main() error {
os.Exit(0)
}
if configFile != "" {
var data []byte
data, err = os.ReadFile(configFile)
if err != nil {
return
}
err = yaml.Unmarshal(data, &cfg)
if err != nil {
return nil, fmt.Errorf("cant parse config, %v", err)
}
if _, err := strconv.Atoi(cfg.Addr); err == nil {
cfg.Addr = ":" + cfg.Addr
}
return &cfg, nil
}
if flag.NArg() == 1 {
upstream = flag.Arg(0)
cfg.Upstream = flag.Arg(0)
} else {
flag.Usage()
os.Exit(2)
}
u, err := url.Parse(upstream)
return &cfg, nil
}
func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
switch {
case aslash && bslash:
return a + b[1:]
case !aslash && !bslash:
return a + "/" + b
}
return a + b
}
func joinURLPath(a, b *url.URL) (path, rawpath string) {
if a.RawPath == "" && b.RawPath == "" {
return singleJoiningSlash(a.Path, b.Path), ""
}
// Same as singleJoiningSlash, but uses EscapedPath to determine
// whether a slash should be added
apath := a.EscapedPath()
bpath := b.EscapedPath()
aslash := strings.HasSuffix(apath, "/")
bslash := strings.HasPrefix(bpath, "/")
switch {
case aslash && bslash:
return a.Path + b.Path[1:], apath + bpath[1:]
case !aslash && !bslash:
return a.Path + "/" + b.Path, apath + "/" + bpath
}
return a.Path + b.Path, apath + bpath
}
func _main() error {
cfg, err := getConfig()
if err != nil {
return err
}
upstream, err := url.Parse(cfg.Upstream)
if err != nil {
return fmt.Errorf("invalid upstream address: %v", err)
}
rp := httputil.NewSingleHostReverseProxy(u)
upstreamQuery := upstream.RawQuery
director := func(req *http.Request) {
req.URL.Scheme = upstream.Scheme
req.Host = upstream.Host
req.URL.Host = upstream.Host
req.URL.Path, req.URL.RawPath = joinURLPath(upstream, req.URL)
if upstreamQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = upstreamQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = upstreamQuery + "&" + req.URL.RawQuery
}
if _, ok := req.Header["User-Agent"]; !ok {
// explicitly disable User-Agent so it's not set to default value
req.Header.Set("User-Agent", "")
}
}
srv := http.Server{
Handler: rp,
Addr: addr,
Handler: &httputil.ReverseProxy{
Director: director,
},
Addr: cfg.Addr,
}
done := make(chan struct{})
@ -78,8 +163,8 @@ func _main() error {
close(done)
}()
log.Printf("cert-file=%s key-file=%s listen-addr=%s upstream-url=%s", certFile, keyFile, srv.Addr, u.String())
if err := srv.ListenAndServeTLS(certFile, keyFile); err != http.ErrServerClosed {
log.Printf("cert-file=%s key-file=%s listen-addr=%s upstream-url=%s", cfg.CertFile, cfg.KeyFile, srv.Addr, upstream.String())
if err := srv.ListenAndServeTLS(cfg.CertFile, cfg.KeyFile); err != http.ErrServerClosed {
return fmt.Errorf("ListenAndServeTLS: %v", err)
}

View file

@ -1,15 +1,10 @@
#!/bin/bash
set -e
UNIT_NAME=proxy
BINARY=rmfake-proxy
UNIT_NAME=rmfakecloud-proxy
BINARY=rmfakecloud-proxy
DESTINATION="/home/root/rmfakecloud"
echo ""
echo "rmFakeCloud proxy installer"
echo ""
# Create destination folder
@ -24,28 +19,24 @@ function unpack(){
# marks all as unsynced so that they are not deleted
function fixsync(){
grep sync ~/.local/share/remarkable/xochitl/*.metadata -l | xargs sed -i 's/synced\": true/synced\": false/'
grep sync ~/.local/share/remarkable/xochitl/*.metadata -l | xargs -r sed -i 's/synced\": true/synced\": false/'
}
function install_proxyservice(){
cloudurl=$1
echo "Setting cloud sync to: ${cloudurl}"
workdir=$DESTINATION
cat > $workdir/proxy.cfg <<EOF
URL=
EOF
cat > /etc/systemd/system/${UNIT_NAME}.service <<EOF
[Unit]
Description=reverse proxy
Description=rmfakecloud reverse proxy
#StartLimitIntervalSec=600
#StartLimitBurst=4
After=home.mount
[Service]
Environment=HOME=/home/root
#EnvironmentFile=$workdir/proxy.cfg
WorkingDirectory=$workdir
ExecStart=$workdir/${BINARY} -cert $workdir/proxy.crt -key $workdir/proxy.key ${cloudurl}
ExecStart=$workdir/${BINARY} -cert $workdir/proxy.bundle.crt -key $workdir/proxy.key ${cloudurl}
[Install]
WantedBy=multi-user.target
@ -61,17 +52,18 @@ function uninstall(){
#rm proxy.key proxy.crt ca.crt ca.srl ca.key proxy.pubkey proxy.csr csr.conf proxy.cfg
rm /usr/local/share/ca-certificates/ca.crt
update-ca-certificates --fresh
rm /etc/systemd/system/proxy.service
rm /etc/systemd/system/${UNIT_NAME}.service
sed -i '/# rmfake_start/,/# rmfake_end/d' /etc/hosts
echo "Marking files as not synced to prevent data loss"
echo "Stopping xochitl..."
systemctl stop xochitl
fixsync
rm -fr $DESTINATION
echo "You can restart xochitl now"
echo "Restart xochitl for the changes to take effect"
}
function generate_certificates(){
# thanks to https://gist.github.com/Soarez/9688998
pushd $DESTINATION
cat <<EOF > csr.conf
[ req ]
@ -103,51 +95,57 @@ subjectAltName=@san
[ san ]
DNS.1 = *.appspot.com
DNS.2 = my.remarkable.com
# DNS.3 = any additional hosts
DNS.2 = *.remarkable.com
DNS.3 = *.cloud.remarkable.com
DNS.4 = *.cloud.remarkable.engineering
DNS.5 = *.rmfakecloud.localhost
DNS.6 = *.internal.cloud.remarkable.com
DNS.7 = *.tectonic.remarkable.com
DNS.8 = *.ping.remarkable.com
EOF
# ca
if [ ! -f ca.crt ]; then
echo "Generating ca..."
echo "Generating CA key and crt..."
openssl genrsa -out ca.key 2048
openssl req -new -sha256 -x509 -key ca.key -out ca.crt -days 3650 -subj /CN=rmfakecloud
rm proxy.key || true
rm proxy.pubkey || true
rm -f proxy.key
rm -f proxy.pubkey
else
echo "CA exists"
fi
if [ ! -f proxy.key ]; then
echo "Generating proxy keys..."
echo "Generating private key..."
openssl genrsa -out proxy.key 2048
rm proxy.pubkey || true
rm -f proxy.pubkey
else
echo "Private key exists"
fi
if [ ! -f proxy.pubkey ]; then
echo "Generating pub key..."
openssl rsa -in proxy.key -pubout -out proxy.pubkey
rm proxy.crt || true
rm -f proxy.crt
else
echo "Pub key exists"
fi
if [ ! -f proxy.crt ]; then
echo "Generating csr and crt..."
openssl req -new -config ./csr.conf -key proxy.key -out proxy.csr
# Signing
openssl x509 -req -in proxy.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out proxy.crt -days 3650 -extfile csr.conf -extensions caext
#cat proxy.crt ca.crt > proxy.bundle.crt
cat proxy.crt ca.crt > proxy.bundle.crt
echo "showing result"
#echo "showing result"
#openssl x509 -in proxy.bundle.crt -text -noout
echo "Generation complete"
echo "Generation complete!"
else
echo "crt exists"
fi
popd
}
function install_certificates(){
@ -171,6 +169,12 @@ function patch_hosts(){
127.0.0.1 service-manager-production-dot-remarkable-production.appspot.com
127.0.0.1 local.appspot.com
127.0.0.1 my.remarkable.com
127.0.0.1 ping.remarkable.com
127.0.0.1 internal.cloud.remarkable.com
127.0.0.1 backtrace-proxy.cloud.remarkable.engineering
127.0.0.1 dev.ping.remarkable.com
127.0.0.1 dev.tectonic.remarkable.com
127.0.0.1 dev.internal.cloud.remarkable.com
# rmfake_end
EOF
fi
@ -178,61 +182,81 @@ EOF
}
function getproxy(){
read -p "Enter your own cloud url: " url
read -p "Enter your own cloud url [http(s)://somehost:port] >" url
echo $url
}
function doinstall(){
echo "Extracting embedded binary..."
unpack
pushd "${DESTINATION}"
generate_certificates
install_certificates
# install proxy
url=$(getproxy)
url=$1
if [ -z $url ]; then
url=$(getproxy)
fi
install_proxyservice $url
echo "Patching /etc/hosts"
patch_hosts
echo "Stoping xochitl.."
systemctl stop xochitl
echo "Fixing sync status..."
fixsync
echo "Starting xochitl..."
systemctl start xochitl
popd
}
case $1 in
"uninstall" )
uninstall
;;
;;
"install" )
doinstall
;;
shift 1
doinstall $1
;;
"setproxy" )
"gencert" )
generate_certificates
;;
"setcloud" )
shift 1
url=$1
if [ $# -lt 1 ]; then
url=$(getproxy)
fi
install_proxyservice $url
;;
;;
* )
cat <<EOF
rmFakeCloud reverse proxy installer
Usage:
install
installs
install [cloudurl]
installs and asks for cloud url
uninstall
uninstall
uninstall, removes everything
setproxy [cloudurl]
gencert
generate certificates
setcloud [cloudurl]
changes the cloud address to
EOF
;;
;;
esac
# Exit from the script with success (0)
exit 0
__ARCHIVE__