mirror of
https://github.com/azukaar/Cosmos-Server.git
synced 2026-10-12 02:11:26 +00:00
[release] v0.21.0-unstable9
This commit is contained in:
+2
-1
@@ -5,8 +5,9 @@
|
||||
- Support for tempFS
|
||||
- Improve support for 0.0.0.0 routes
|
||||
- Reworked the setting page for better clarity
|
||||
- Added support for HTTP2 Cleartext (H2C)
|
||||
- Added advanced DNS options (challenge related, thanks @moham96)
|
||||
- Added trusted proxy option (Thanks @InterN0te)
|
||||
- Added trusted proxy option for X-Forwarded-For (Thanks @InterN0te)
|
||||
- Reduce SmartShield false positive on the server panel by having two level of strictness (UI/panel vs. login)
|
||||
- Rclone rework, no more sub processes (increased performance and reliability)
|
||||
- Added the ability to manage Restic locks from the UI
|
||||
|
||||
@@ -81,6 +81,7 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
|
||||
UseHost: routeConfig.UseHost,
|
||||
Host: routeConfig.Host,
|
||||
AcceptInsecureHTTPSTarget: routeConfig.AcceptInsecureHTTPSTarget === true,
|
||||
UseH2C: routeConfig.UseH2C === true,
|
||||
UsePathPrefix: routeConfig.UsePathPrefix,
|
||||
PathPrefix: routeConfig.PathPrefix,
|
||||
StripPathPrefix: routeConfig.StripPathPrefix,
|
||||
@@ -390,7 +391,14 @@ const RouteManagement = ({ routeConfig, routeNames, config, TargetContainer, noC
|
||||
name="SkipURLClean"
|
||||
label={t('mgmt.urls.edit.advancedSettings.skipURLCleanCheckbox.skipURLCleanLabel')}
|
||||
formik={formik}
|
||||
/></>}
|
||||
/>
|
||||
|
||||
{(formik.values.Mode === "SERVAPP" || formik.values.Mode === "PROXY") && <CosmosCheckbox
|
||||
name="UseH2C"
|
||||
label={t('mgmt.urls.edit.useH2CCheckbox.useH2CLabel')}
|
||||
formik={formik}
|
||||
/>}
|
||||
</>}
|
||||
|
||||
<Alert severity='warning'>
|
||||
{t('mgmt.urls.edit.advancedSettings.filterIpWarning')}
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
"mgmt.config.security.adminRestrictions.adminRestrictionsInfo": "Use those options to restrict access to the admin panel. Be careful, if you lock yourself out, you will need to manually edit the config file. To restrict the access to your local network, you can use the 'Admin Whitelist' with the IP range 192.168.0.0/16",
|
||||
"mgmt.config.security.adminRestrictions.adminWhitelistInput.adminWhitelistHelperText": "Comma separated list of IPs that will be allowed to access the admin panel",
|
||||
"mgmt.config.security.adminRestrictions.adminWhitelistInput.adminWhitelistLabel": "Admin Whitelist Inbound IPs and/or IP ranges (comma separated)",
|
||||
"mgmt.config.security.trustedProxiesInput.trustedProxiesLabel": "Trusted proxies allow X-Forwarded-For from IP/IP range",
|
||||
"mgmt.config.security.trustedProxiesInput.trustedProxiesLabel": "Comma separated trusted proxies allow X-Forwarded-For from IP/IP range (can also be a URL to a list of IPs like the cloudflare list)",
|
||||
"mgmt.config.security.trustedProxiesInput.trustedProxiesHelperText": "Comma separated list of IPs/IP ranges of upstream proxies that are trusted to provide the real client IP via X-Forwarded-For header",
|
||||
"mgmt.config.security.adminRestrictionsTitle": "Admin Restrictions",
|
||||
"mgmt.config.security.encryption.authPubKeyTitle": "Authentication Public Key",
|
||||
@@ -679,6 +679,7 @@
|
||||
"mgmt.urls.edit.basicSecurity.smartShield.noReffererCheckbox.noReffererLabel": "Block requests without Referer header",
|
||||
"mgmt.urls.edit.basicSecurityTitle": "Basic Security",
|
||||
"mgmt.urls.edit.insecureHttpsCheckbox.insecureHttpsLabel": "Accept Insecure HTTPS Target (not recommended)",
|
||||
"mgmt.urls.edit.useH2CCheckbox.useH2CLabel": "Use HTTP/2 Cleartext (H2C)",
|
||||
"mgmt.urls.edit.newUrlTitle": "new URL",
|
||||
"mgmt.urls.edit.updateSuccess": "Route updated successfully",
|
||||
"mgmt.urls.edit.nameValidation": "Route Name already exists. Name must be unique.",
|
||||
|
||||
@@ -217,7 +217,6 @@
|
||||
"mgmt.config.security.geoBlockSelection.varBlock": "bloquer",
|
||||
"mgmt.config.security.geoblock.resetToDefaultButton": "Réinitialiser par défaut (pays les plus dangereux)",
|
||||
"mgmt.config.security.invertBlacklistCheckbox.invertBlacklistLabel": "Utiliser la liste comme liste blanche au lieu de liste noire",
|
||||
"mgmt.config.security.trustedProxiesInput.trustedProxiesLabel": "Les proxies de confiance autorisent X-Forwarded-For depuis une IP/plage d'IP",
|
||||
"mgmt.config.security.trustedProxiesInput.trustedProxiesHelperText": "Liste d'IPs/plages d'IPs séparées par des virgules des proxies en amont auxquels on fait confiance pour fournir l'IP réelle du client via l'en-tête X-Forwarded-For",
|
||||
"mgmt.constellation.dns.resetButton": "Réinitialiser",
|
||||
"mgmt.constellation.dnsBlocklistsTitle": "Listes de blocage DNS",
|
||||
|
||||
@@ -20,6 +20,7 @@ VOLUME /config
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y ca-certificates openssl fdisk mergerfs snapraid \
|
||||
curl unzip wget avahi-daemon avahi-utils samba fuse3 \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
+2
-1
@@ -10,7 +10,8 @@ WORKDIR /app
|
||||
|
||||
ENV PATH=$PATH:/usr/local/go/bin
|
||||
|
||||
RUN apt-get update && apt-get install -y ca-certificates openssl fdisk mergerfs snapraid && \
|
||||
RUN apt-get update && apt-get install -y ca-certificates openssl fdisk mergerfs snapraid \
|
||||
avahi-daemon avahi-utils samba fuse3 unzip && \
|
||||
apt-get install -y --no-install-recommends wget curl && \
|
||||
apt-get install -y --no-install-recommends nodejs && \
|
||||
wget https://golang.org/dl/go1.23.2.linux-amd64.tar.gz && \
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cosmos-server",
|
||||
"version": "0.21.0-unstable8",
|
||||
"version": "0.21.0-unstable9",
|
||||
"description": "",
|
||||
"main": "test-server.js",
|
||||
"bugs": {
|
||||
|
||||
@@ -15,7 +15,7 @@ func ConfigApiRestart(w http.ResponseWriter, req *http.Request) {
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"status": "OK",
|
||||
})
|
||||
utils.RestartServer()
|
||||
utils.RestartServer(0)
|
||||
} else {
|
||||
utils.Error("Restart: Method not allowed" + req.Method, nil)
|
||||
utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001")
|
||||
|
||||
@@ -136,7 +136,11 @@ func startNebula() error {
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create nebula instance: %w", err)
|
||||
utils.Error("failed to create nebula instance, need to restart the process", err)
|
||||
|
||||
// TODO: need a way to avoid restart loops (check if Nebula ever started?)
|
||||
// We need a full restart
|
||||
// utils.RestartServer(1)
|
||||
}
|
||||
|
||||
// Actually start the nebula service (brings up TUN interface)
|
||||
|
||||
@@ -69,7 +69,6 @@ func Connect() error {
|
||||
DockerIsConnected = false
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
DockerClient = client
|
||||
DockerContext = ctx
|
||||
|
||||
+43
-38
@@ -16,6 +16,8 @@ import (
|
||||
"github.com/azukaar/cosmos-server/src/utils"
|
||||
"github.com/azukaar/cosmos-server/src/docker"
|
||||
"github.com/azukaar/cosmos-server/src/constellation"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
|
||||
@@ -58,56 +60,59 @@ func NewProxy(targetHost string, AcceptInsecureHTTPSTarget bool, DisableHeaderHa
|
||||
var transport http.RoundTripper
|
||||
var targetURL *url.URL
|
||||
var err error
|
||||
|
||||
// if strings.HasPrefix(targetHost, "http://unix://") {
|
||||
// // Unix socket handling
|
||||
// socketPath := strings.TrimPrefix(targetHost, "http://unix://")
|
||||
// transport = &http.Transport{
|
||||
// DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
|
||||
// return net.Dial("unix", socketPath)
|
||||
// },
|
||||
// }
|
||||
// // Use a dummy URL for the director
|
||||
// targetURL, _ = url.Parse("http://unix-socket")
|
||||
// } else {
|
||||
// Regular HTTP/HTTPS handling
|
||||
|
||||
targetURL, err = url.Parse(targetHost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
targetURL, err = url.Parse(targetHost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
customTransport := &http.Transport{}
|
||||
dialer := &net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
KeepAlive: 5 * time.Second,
|
||||
}
|
||||
|
||||
if constellation.ConstellationConnected() {
|
||||
currIp, err := constellation.GetCurrentDeviceIP()
|
||||
if err != nil {
|
||||
utils.Error("Custom tunnel transport", err)
|
||||
} else {
|
||||
customTransport.DialContext = (&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
KeepAlive: 5 * time.Second,
|
||||
Resolver: &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return net.Dial(network, currIp + ":53")
|
||||
},
|
||||
},
|
||||
}).DialContext
|
||||
if utils.GetMainConfig().ConstellationConfig.Enabled {
|
||||
dialer.Resolver = &net.Resolver{
|
||||
PreferGo: true,
|
||||
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
currConIp, err := constellation.GetCurrentDeviceIP()
|
||||
if err == nil {
|
||||
// Try Constellation DNS first
|
||||
conn, err := net.Dial(network, currConIp+":53")
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to system DNS
|
||||
return net.Dial(network, address)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if route.UseH2C {
|
||||
transport = &http2.Transport{
|
||||
AllowHTTP: true,
|
||||
DialTLSContext: func(ctx context.Context, network, addr string, _ *tls.Config) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, network, addr)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
customTransport := &http.Transport{
|
||||
DialContext: dialer.DialContext,
|
||||
}
|
||||
if AcceptInsecureHTTPSTarget {
|
||||
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
|
||||
transport = customTransport
|
||||
// }
|
||||
}
|
||||
|
||||
proxy := &httputil.ReverseProxy{
|
||||
Transport: transport,
|
||||
Transport: transport,
|
||||
FlushInterval: -1,
|
||||
}
|
||||
|
||||
|
||||
proxy.Director = func(req *http.Request) {
|
||||
originalScheme := "http"
|
||||
if utils.IsHTTPS {
|
||||
|
||||
@@ -261,6 +261,7 @@ type ProxyRouteConfig struct {
|
||||
TunneledHost string `yaml:"tunneled_host,omitempty"`
|
||||
ExtraHeaders map[string]string `yaml:"extra_headers,omitempty"`
|
||||
SkipURLClean bool `yaml:"skip_url_clean"`
|
||||
UseH2C bool `yaml:"use_h2c"`
|
||||
Const_IsTunneled bool `yaml:"-", json:"-"`
|
||||
}
|
||||
|
||||
|
||||
+57
-4
@@ -439,13 +439,13 @@ func SaveConfigTofile(config Config) {
|
||||
Log("Config file saved.")
|
||||
}
|
||||
|
||||
func RestartServer() {
|
||||
func RestartServer(code int) {
|
||||
Log("Restarting server...")
|
||||
WaitForAllJobs()
|
||||
if StopAllRCloneProcess != nil {
|
||||
StopAllRCloneProcess(false)
|
||||
}
|
||||
os.Exit(0)
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
func SoftRestartServer() {
|
||||
@@ -897,10 +897,63 @@ func GetClientIP(req *http.Request) string {
|
||||
return remoteAddr
|
||||
}
|
||||
|
||||
var (
|
||||
trustedProxyURLCache = map[string][]string{}
|
||||
trustedProxyURLCacheLock sync.Mutex
|
||||
)
|
||||
|
||||
func fetchIPRangesFromURL(url string) ([]string, error) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ranges []string
|
||||
for _, line := range strings.Split(string(body), "\n") {
|
||||
line = strings.TrimSpace(line)
|
||||
if line != "" {
|
||||
ranges = append(ranges, line)
|
||||
}
|
||||
}
|
||||
return ranges, nil
|
||||
}
|
||||
|
||||
func getTrustedProxyRanges(url string) []string {
|
||||
trustedProxyURLCacheLock.Lock()
|
||||
defer trustedProxyURLCacheLock.Unlock()
|
||||
|
||||
if cached, ok := trustedProxyURLCache[url]; ok {
|
||||
return cached
|
||||
}
|
||||
|
||||
ranges, err := fetchIPRangesFromURL(url)
|
||||
if err != nil {
|
||||
Error("IsTrustedProxy: failed to fetch URL "+url, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
trustedProxyURLCache[url] = ranges
|
||||
return ranges
|
||||
}
|
||||
|
||||
func IsTrustedProxy(ip string) bool {
|
||||
for _, trustedProxy := range GetMainConfig().HTTPConfig.TrustedProxies {
|
||||
if isInRange, _ := IPInRange(ip, trustedProxy); isInRange {
|
||||
return true
|
||||
if strings.HasPrefix(trustedProxy, "http://") || strings.HasPrefix(trustedProxy, "https://") {
|
||||
for _, r := range getTrustedProxyRanges(trustedProxy) {
|
||||
if isInRange, _ := IPInRange(ip, r); isInRange {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if isInRange, _ := IPInRange(ip, trustedProxy); isInRange {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user