diff --git a/src/main.go b/src/main.go
index 2ca0d9f..5ffa919 100644
--- a/src/main.go
+++ b/src/main.go
@@ -52,7 +52,7 @@ var logOutputToFile = flag.Bool("log", true, "Log terminal output to file")
var (
name = "Zoraxy"
- version = "3.0.5"
+ version = "3.0.6"
nodeUUID = "generic"
development = false //Set this to false to use embedded web fs
bootTime = time.Now().Unix()
diff --git a/src/mod/dynamicproxy/Server.go b/src/mod/dynamicproxy/Server.go
index 129192b..e67ea0c 100644
--- a/src/mod/dynamicproxy/Server.go
+++ b/src/mod/dynamicproxy/Server.go
@@ -14,11 +14,16 @@ import (
Main server for dynamic proxy core
Routing Handler Priority (High to Low)
- - Blacklist
- - Whitelist
+ - Special Routing Rule (e.g. acme)
- Redirectable
- Subdomain Routing
- - Vitrual Directory Routing
+ - Access Router
+ - Blacklist
+ - Whitelist
+ - Basic Auth
+ - Vitrual Directory Proxy
+ - Subdomain Proxy
+ - Root router (default site router)
*/
func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
diff --git a/src/mod/dynamicproxy/dpcore/dpcore.go b/src/mod/dynamicproxy/dpcore/dpcore.go
index d5ffe2c..a14a732 100644
--- a/src/mod/dynamicproxy/dpcore/dpcore.go
+++ b/src/mod/dynamicproxy/dpcore/dpcore.go
@@ -304,9 +304,13 @@ func addXForwardedForHeader(req *http.Request) {
if req.Header.Get("X-Real-Ip") == "" {
//Check if CF-Connecting-IP header exists
CF_Connecting_IP := req.Header.Get("CF-Connecting-IP")
+ Fastly_Client_IP := req.Header.Get("Fastly-Client-IP")
if CF_Connecting_IP != "" {
//Use CF Connecting IP
req.Header.Set("X-Real-Ip", CF_Connecting_IP)
+ } else if Fastly_Client_IP != "" {
+ //Use Fastly Client IP
+ req.Header.Set("X-Real-Ip", Fastly_Client_IP)
} else {
// Not exists. Fill it in with first entry in X-Forwarded-For
ips := strings.Split(clientIP, ",")
diff --git a/src/mod/dynamicproxy/typedef.go b/src/mod/dynamicproxy/typedef.go
index dad1927..04ded0c 100644
--- a/src/mod/dynamicproxy/typedef.go
+++ b/src/mod/dynamicproxy/typedef.go
@@ -72,10 +72,21 @@ type BasicAuthExceptionRule struct {
PathPrefix string
}
+// Header injection direction type
+type HeaderDirection int
+
+const (
+ HeaderDirection_ZoraxyToUpstream HeaderDirection = 0 //Inject (or remove) header to request out-going from Zoraxy to backend server
+ HeaderDirection_ZoraxyToDownstream HeaderDirection = 1 //Inject (or remove) header to request out-going from Zoraxy to client (e.g. browser)
+)
+
// User defined headers to add into a proxy endpoint
type UserDefinedHeader struct {
- Key string
- Value string
+ Direction HeaderDirection
+ Key string
+ Value string
+ IsRemove bool //Instead of set, remove this key instead
+ IsAppend bool //Instead of set, append to the current one with "," as seperator
}
// A Virtual Directory endpoint, provide a subset of ProxyEndpoint for better
diff --git a/src/mod/sshprox/utils.go b/src/mod/sshprox/utils.go
index 46801c0..082c8d9 100644
--- a/src/mod/sshprox/utils.go
+++ b/src/mod/sshprox/utils.go
@@ -9,13 +9,13 @@ import (
"time"
)
-//Rewrite url based on proxy root
+// Rewrite url based on proxy root (default site)
func RewriteURL(rooturl string, requestURL string) (*url.URL, error) {
rewrittenURL := strings.TrimPrefix(requestURL, rooturl)
return url.Parse(rewrittenURL)
}
-//Check if the current platform support web.ssh function
+// Check if the current platform support web.ssh function
func IsWebSSHSupported() bool {
//Check if the binary exists in system/gotty/
binary := "gotty_" + runtime.GOOS + "_" + runtime.GOARCH
@@ -34,7 +34,7 @@ func IsWebSSHSupported() bool {
return true
}
-//Check if a given domain and port is a valid ssh server
+// Check if a given domain and port is a valid ssh server
func IsSSHConnectable(ipOrDomain string, port int) bool {
timeout := time.Second * 3
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ipOrDomain, port), timeout)
@@ -60,7 +60,7 @@ func IsSSHConnectable(ipOrDomain string, port int) bool {
return string(buf[:7]) == "SSH-2.0"
}
-//Check if the port is used by other process or application
+// Check if the port is used by other process or application
func isPortInUse(port int) bool {
address := fmt.Sprintf(":%d", port)
listener, err := net.Listen("tcp", address)
diff --git a/src/mod/tcpprox/conn.go b/src/mod/tcpprox/conn.go
index 9f8c1d7..2f53f70 100644
--- a/src/mod/tcpprox/conn.go
+++ b/src/mod/tcpprox/conn.go
@@ -7,6 +7,7 @@ import (
"net"
"strconv"
"sync"
+ "sync/atomic"
"time"
)
@@ -38,8 +39,12 @@ func isReachable(target string) bool {
return true
}
-func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *int64) {
- io.Copy(conn1, conn2)
+func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *atomic.Int64) {
+ n, err := io.Copy(conn1, conn2)
+ if err != nil {
+ //Add to accumulator
+ accumulator.Add(n)
+ }
conn1.Close()
log.Println("[←]", "close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]")
//conn2.Close()
@@ -47,7 +52,7 @@ func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *i
wg.Done()
}
-func forward(conn1 net.Conn, conn2 net.Conn, aTob *int64, bToa *int64) {
+func forward(conn1 net.Conn, conn2 net.Conn, aTob *atomic.Int64, bToa *atomic.Int64) {
log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
var wg sync.WaitGroup
// wait tow goroutines
@@ -158,6 +163,8 @@ func (c *ProxyRelayConfig) Start() error {
err = c.Port2port(c.PortA, c.PortB, stopChan)
} else if c.Mode == ProxyMode_Starter {
err = c.Host2host(c.PortA, c.PortB, stopChan)
+ } else if c.Mode == ProxyMode_UDP {
+ err = c.ForwardUDP(c.PortA, c.PortB, stopChan)
}
if err != nil {
c.Running = false
diff --git a/src/mod/tcpprox/tcpprox.go b/src/mod/tcpprox/tcpprox.go
index c5944e6..f030bdf 100644
--- a/src/mod/tcpprox/tcpprox.go
+++ b/src/mod/tcpprox/tcpprox.go
@@ -3,6 +3,8 @@ package tcpprox
import (
"errors"
"net"
+ "sync"
+ "sync/atomic"
"github.com/google/uuid"
"imuslab.com/zoraxy/mod/database"
@@ -20,6 +22,7 @@ const (
ProxyMode_Listen = 0
ProxyMode_Transport = 1
ProxyMode_Starter = 2
+ ProxyMode_UDP = 3
)
type ProxyRelayOptions struct {
@@ -31,16 +34,16 @@ type ProxyRelayOptions struct {
}
type ProxyRelayConfig struct {
- UUID string //A UUIDv4 representing this config
- Name string //Name of the config
- Running bool //If the service is running
- PortA string //Ports A (config depends on mode)
- PortB string //Ports B (config depends on mode)
- Mode int //Operation Mode
- Timeout int //Timeout for connection in sec
- stopChan chan bool //Stop channel to stop the listener
- aTobAccumulatedByteTransfer int64 //Accumulated byte transfer from A to B
- bToaAccumulatedByteTransfer int64 //Accumulated byte transfer from B to A
+ UUID string //A UUIDv4 representing this config
+ Name string //Name of the config
+ Running bool //If the service is running
+ PortA string //Ports A (config depends on mode)
+ PortB string //Ports B (config depends on mode)
+ Mode int //Operation Mode
+ Timeout int //Timeout for connection in sec
+ stopChan chan bool //Stop channel to stop the listener
+ aTobAccumulatedByteTransfer atomic.Int64 //Accumulated byte transfer from A to B
+ bToaAccumulatedByteTransfer atomic.Int64 //Accumulated byte transfer from B to A
parent *Manager `json:"-"`
}
@@ -57,7 +60,8 @@ type Manager struct {
Configs []*ProxyRelayConfig
//Realtime Statistics
- Connections int //currently connected connect counts
+ Connections int //currently connected connect counts
+ UDPClientMap sync.Map //map storing the UDP client-server connections
}
func NewTCProxy(options *Options) *Manager {
@@ -94,6 +98,11 @@ func NewTCProxy(options *Options) *Manager {
}
func (m *Manager) NewConfig(config *ProxyRelayOptions) string {
+ //Generate two zero value for atomic int64
+ aAcc := atomic.Int64{}
+ bAcc := atomic.Int64{}
+ aAcc.Store(0)
+ bAcc.Store(0)
//Generate a new config from options
configUUID := uuid.New().String()
thisConfig := ProxyRelayConfig{
@@ -105,8 +114,8 @@ func (m *Manager) NewConfig(config *ProxyRelayOptions) string {
Mode: config.Mode,
Timeout: config.Timeout,
stopChan: nil,
- aTobAccumulatedByteTransfer: 0,
- bToaAccumulatedByteTransfer: 0,
+ aTobAccumulatedByteTransfer: aAcc,
+ bToaAccumulatedByteTransfer: bAcc,
parent: m,
}
diff --git a/src/mod/tcpprox/udpprox.go b/src/mod/tcpprox/udpprox.go
new file mode 100644
index 0000000..553e85b
--- /dev/null
+++ b/src/mod/tcpprox/udpprox.go
@@ -0,0 +1,89 @@
+package tcpprox
+
+import (
+ "log"
+ "net"
+)
+
+/*
+ UDP Proxy Module
+*/
+
+// Information maintained for each client/server connection
+type udpClientServerConn struct {
+ ClientAddr *net.UDPAddr // Address of the client
+ ServerConn *net.UDPConn // UDP connection to server
+}
+
+// Generate a new connection by opening a UDP connection to the server
+func createNewUDPConn(srvAddr, cliAddr *net.UDPAddr) *udpClientServerConn {
+ conn := new(udpClientServerConn)
+ conn.ClientAddr = cliAddr
+ srvudp, err := net.DialUDP("udp", nil, srvAddr)
+ if err != nil {
+ return nil
+ }
+ conn.ServerConn = srvudp
+ return conn
+}
+
+// Start listener, return inbound lisener and proxy target UDP address
+func initUDPConnections(listenAddr string, targetAddress string) (*net.UDPConn, *net.UDPAddr, error) {
+ // Set up Proxy
+ saddr, err := net.ResolveUDPAddr("udp", listenAddr)
+ if err != nil {
+ return nil, nil, err
+ }
+ inboundConn, err := net.ListenUDP("udp", saddr)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ log.Println("Proxy serving on port %s\n", listenAddr)
+
+ outboundConn, err := net.ResolveUDPAddr("udp", targetAddress)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return inboundConn, outboundConn, nil
+}
+
+func (c *ProxyRelayConfig) ForwardUDP(address1, address2 string, stopChan chan bool) error {
+ lisener, targetAddr, err := initUDPConnections(address1, address2)
+ if err != nil {
+ return err
+ }
+
+ var buffer [1500]byte
+ for {
+ n, cliaddr, err := lisener.ReadFromUDP(buffer[0:])
+ if err != nil {
+ continue
+ }
+ c.aTobAccumulatedByteTransfer.Add(int64(n))
+ saddr := cliaddr.String()
+ dlock()
+ conn, found := ClientDict[saddr]
+ if !found {
+ conn = createNewUDPConn(targetAddr, cliaddr)
+ if conn == nil {
+ dunlock()
+ continue
+ }
+ ClientDict[saddr] = conn
+ dunlock()
+ Vlogf(2, "Created new connection for client %s\n", saddr)
+ // Fire up routine to manage new connection
+ go RunConnection(conn)
+ } else {
+ Vlogf(5, "Found connection for client %s\n", saddr)
+ dunlock()
+ }
+ // Relay to server
+ _, err = conn.ServerConn.Write(buffer[0:n])
+ if checkreport(1, err) {
+ continue
+ }
+ }
+}
diff --git a/src/web/components/rproot.html b/src/web/components/rproot.html
index add7495..667b5c1 100644
--- a/src/web/components/rproot.html
+++ b/src/web/components/rproot.html
@@ -258,7 +258,7 @@
setTimeout(function(){
//Update the checkbox
- msgbox("Proxy Root Updated");
+ msgbox("Default Site Updated");
}, 100);
})
diff --git a/src/web/img/logo_white.ai b/src/web/img/logo_white.ai
new file mode 100644
index 0000000..d09ffb0
--- /dev/null
+++ b/src/web/img/logo_white.ai
@@ -0,0 +1,1512 @@
+%PDF-1.5
%
+1 0 obj
<>/OCGs[5 0 R 26 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<>stream
+
+
+
+
+ application/pdf
+
+
+ 列印
+
+
+
+
+ 2024-06-04T15:13:48+08:00
+ 2024-06-04T15:13:48+08:00
+ 2024-06-04T15:13:23+08:00
+ Adobe Illustrator CS6 (Windows)
+
+
+
+ 256
+ 64
+ JPEG
+ /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAQAEAAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4qpJcRu5QdR0Pjiqri
qTeYNG+tx/WIB/pKDcD9tR2+Y7Zk6fNwmjycbUYeIWOaU+X9FN3L9YnX/Rozsp/bYdvkO+ZOozcI
oc3H0+HiNnky/Na7FZLKsa8m+geOKtxyK6hl6HFV2KuxV1RirqjxxV1R44q6o8cVdirsVdirsVdi
rsVdirsVdirsVdirsVdirsVdirsVdirsVQ15LQemOp6/LFUGCQajriqZxFzGC4o3fFV2KuAAFAKD
298VdiqXXDSGU89iOg9sVXW0vpyUP2W2OKo/FXYqpyRsxBGKrPRf2xVpkK9aYq3CpLV7DFVfFXYq
7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYqlsz85Wb32+WKqlpGHkqei7/TiqOxVjmpeaWS
VorJVKqaGZt6/wCqMzcWl2uThZNVvUUJbeatQRx64WZO4pxP0Ef0yyWkieWzXHVSHNlNpdQ3Vuk8
Jqj/AHg9wcwJwMTRc+EhIWFl5GCnMdV6/LIskFiqZQPyiU96b/Rtiq/FXYq4mgqcVQ7Eu/6sVV1U
KtMVc7hRU/QMVUecjHb7hirucinev04qqo4Ye/cYq6QkISOuKqaykKa7ntirQMpINTv92Kr5JCpo
B9OKrKzHffFXLK6nfcdxiqv1GKqLPIrUJxVWBBFR0xVRMjl6Kdu2KrpC6qCD88VbicsN+oxVfiqj
6js9AdidsVQGKoyx+y/zGKtaq7pptyyfaEbUp8uuWYhcg15TUSwHNu6l2Kso8nu5huUP2FZSvzIN
f1DMDWDcOdpDsU9m/un/ANU/qzDcxLcVR9n/AHI+ZxVWxV2KqUz/ALI+nFW4UoOR6npiqpiqhMav
TwxVVjUBB77nFW3UMpH3YqoxGjj3xVUm+wcVU4lDNv0GKq+KuIHU9sVWmVB3r8sVUZGDNUYqrRfY
GKtSpyWo6jFVIOQpXxxVfCn7R+jFVRl5KRiqjEaPTx2xVVkNEJxVTgX4ifDFUFIvF2XwOKq9k4Dl
T+10+YxVFuiujI4qrAqw8QdjhBpBFsL1PQry0lYojSwE/A6itB4MB0zZ4s8ZDzdbkwSifJC2+nX1
w4SKFmJ70IA+ZO2WSyRjzLXHHI8gzLSdOWwtBDXlIx5SMO7Hw9hmszZOOVuyxY+AUr3b8YSO7bDK
m1AYqmNsvGFfff78VVMVWu3Fa9+2KqMa8236d8VRGKuxVDyj4ziquhqoPtirmNFJxVQjHxjFVWb7
BxVZB1OKq2KqErEtx7Dtiq9YVH2tziqyZQGFBTbFVWL+7H+ffFXSPxX3PTFVDiePLtiqtE9Vp3GK
r8VUJRR6+O+KtytVV998VVIlog998VQt7FRhIOh2PzxVDgkEEbEdMVTKJ2eMMwoTiq7FXYq7FUvu
JHeQ8hSmwHhiq2KMySBR07/LFUyAoKDFXYqoSsS5Hh0xVpZGUUFMVb9Z/bFVySsWANN8VXSpyFR1
GKqSyMm34HFW2kZ9u3hiq+KMruepxVub7BxVZB1OKq2KqEqkOT2PQ4q367U6b4qtfmfibv0xVVi/
ux9OKqTEu+30Yqr8Rx49sVUN0f5YqiAQRUdDiqyVap7jfFVFRyYDFUTirTKGUqdwcVQ8dnSQljVR
9kePzxVE4qkvmCHUUT63aTyKqj97ErGgA/aA/XmVp5RO0g42ojIbgpZox1e/uKG6lWBN5X5H/gR7
nL83BAchbRh45nmaZaBQUzXOwUbi3Egquzj8cVXQQiJfFj1OKqmKuxV1B4Yq6g8MVdQeGKuoPDFX
Yq4qD1FcVaCqOgpireKuxV1BirsVcQD1xVoKo6AYq3QYq6gxV1B4Yq7FXUGKu2HtiqyVwFoOpxVb
AvVvoGKquKuxV2KuxV2KqdvbQW8fpwII0qTxHiclKRkbLGMQBQVMiydirsVdirsVdirsVdirsVdi
rsVdirsVdirsVdirsVdirsVdirsVdirsVWyKWWgxVTEB7n7sVVgABQdMVdir/9k=
+
+
+
+
+
+ uuid:668719e4-7b53-4dd0-81a8-e66057327e2f
+ xmp.did:C6694DEE4122EF11AB7A82501564F938
+ uuid:5D20892493BFDB11914A8590D31508C8
+ proof:pdf
+
+ uuid:b533ec92-b0b8-44da-8973-f98fbe57eccc
+ xmp.did:B2A3B29C01D6ED11890DEB5FB6D81883
+ uuid:5D20892493BFDB11914A8590D31508C8
+ proof:pdf
+
+
+
+
+ saved
+ xmp.iid:B2A3B29C01D6ED11890DEB5FB6D81883
+ 2023-04-08T19:36:33+08:00
+ Adobe Illustrator CS6 (Windows)
+ /
+
+
+ saved
+ xmp.iid:C6694DEE4122EF11AB7A82501564F938
+ 2024-06-04T15:13:23+08:00
+ Adobe Illustrator CS6 (Windows)
+ /
+
+
+
+
+
+ Document
+ Print
+
+
+ False
+ False
+ 1
+
+ 600.000000
+ 200.000000
+ Pixels
+
+
+
+ Cyan
+ Magenta
+ Yellow
+
+
+
+
+
+ 預設色票群組
+ 0
+
+
+
+ 白色
+ RGB
+ PROCESS
+ 255
+ 255
+ 255
+
+
+ 黑色
+ RGB
+ PROCESS
+ 35
+ 24
+ 21
+
+
+ CMYK 紅色
+ RGB
+ PROCESS
+ 230
+ 0
+ 18
+
+
+ CMYK 黃色
+ RGB
+ PROCESS
+ 255
+ 241
+ 0
+
+
+ CMYK 綠色
+ RGB
+ PROCESS
+ 0
+ 153
+ 68
+
+
+ CMYK 青色
+ RGB
+ PROCESS
+ 0
+ 160
+ 233
+
+
+ CMYK 藍色
+ RGB
+ PROCESS
+ 29
+ 32
+ 136
+
+
+ CMYK 洋紅色
+ RGB
+ PROCESS
+ 228
+ 0
+ 127
+
+
+ C=15 M=100 Y=90 K=10
+ RGB
+ PROCESS
+ 195
+ 13
+ 35
+
+
+ C=0 M=90 Y=85 K=0
+ RGB
+ PROCESS
+ 232
+ 56
+ 40
+
+
+ C=0 M=80 Y=95 K=0
+ RGB
+ PROCESS
+ 234
+ 85
+ 20
+
+
+ C=0 M=50 Y=100 K=0
+ RGB
+ PROCESS
+ 243
+ 152
+ 0
+
+
+ C=0 M=35 Y=85 K=0
+ RGB
+ PROCESS
+ 248
+ 182
+ 45
+
+
+ C=5 M=0 Y=90 K=0
+ RGB
+ PROCESS
+ 250
+ 238
+ 0
+
+
+ C=20 M=0 Y=100 K=0
+ RGB
+ PROCESS
+ 218
+ 224
+ 0
+
+
+ C=50 M=0 Y=100 K=0
+ RGB
+ PROCESS
+ 143
+ 195
+ 31
+
+
+ C=75 M=0 Y=100 K=0
+ RGB
+ PROCESS
+ 34
+ 172
+ 56
+
+
+ C=85 M=10 Y=100 K=10
+ RGB
+ PROCESS
+ 0
+ 145
+ 58
+
+
+ C=90 M=30 Y=95 K=30
+ RGB
+ PROCESS
+ 0
+ 105
+ 52
+
+
+ C=75 M=0 Y=75 K=0
+ RGB
+ PROCESS
+ 19
+ 174
+ 103
+
+
+ C=80 M=10 Y=45 K=0
+ RGB
+ PROCESS
+ 0
+ 162
+ 154
+
+
+ C=70 M=15 Y=0 K=0
+ RGB
+ PROCESS
+ 46
+ 167
+ 224
+
+
+ C=85 M=50 Y=0 K=0
+ RGB
+ PROCESS
+ 3
+ 110
+ 184
+
+
+ C=100 M=95 Y=5 K=0
+ RGB
+ PROCESS
+ 23
+ 42
+ 136
+
+
+ C=100 M=100 Y=25 K=25
+ RGB
+ PROCESS
+ 23
+ 28
+ 97
+
+
+ C=75 M=100 Y=0 K=0
+ RGB
+ PROCESS
+ 96
+ 25
+ 134
+
+
+ C=50 M=100 Y=0 K=0
+ RGB
+ PROCESS
+ 146
+ 7
+ 131
+
+
+ C=35 M=100 Y=35 K=10
+ RGB
+ PROCESS
+ 164
+ 11
+ 93
+
+
+ C=10 M=100 Y=50 K=0
+ RGB
+ PROCESS
+ 215
+ 0
+ 81
+
+
+ C=0 M=95 Y=20 K=0
+ RGB
+ PROCESS
+ 230
+ 22
+ 115
+
+
+ C=25 M=25 Y=40 K=0
+ RGB
+ PROCESS
+ 201
+ 188
+ 156
+
+
+ C=40 M=45 Y=50 K=5
+ RGB
+ PROCESS
+ 164
+ 139
+ 120
+
+
+ C=50 M=50 Y=60 K=25
+ RGB
+ PROCESS
+ 122
+ 106
+ 86
+
+
+ C=55 M=60 Y=65 K=40
+ RGB
+ PROCESS
+ 96
+ 76
+ 63
+
+
+ C=25 M=40 Y=65 K=0
+ RGB
+ PROCESS
+ 201
+ 160
+ 99
+
+
+ C=30 M=50 Y=75 K=10
+ RGB
+ PROCESS
+ 178
+ 130
+ 71
+
+
+ C=35 M=60 Y=80 K=25
+ RGB
+ PROCESS
+ 149
+ 97
+ 52
+
+
+ C=40 M=65 Y=90 K=35
+ RGB
+ PROCESS
+ 127
+ 79
+ 33
+
+
+ C=40 M=70 Y=100 K=50
+ RGB
+ PROCESS
+ 106
+ 57
+ 6
+
+
+ C=50 M=70 Y=80 K=70
+ RGB
+ PROCESS
+ 64
+ 34
+ 15
+
+
+
+
+
+ 灰階
+ 1
+
+
+
+ C=0 M=0 Y=0 K=100
+ RGB
+ PROCESS
+ 35
+ 24
+ 21
+
+
+ C=0 M=0 Y=0 K=90
+ RGB
+ PROCESS
+ 62
+ 58
+ 57
+
+
+ C=0 M=0 Y=0 K=80
+ RGB
+ PROCESS
+ 89
+ 87
+ 87
+
+
+ C=0 M=0 Y=0 K=70
+ RGB
+ PROCESS
+ 114
+ 113
+ 113
+
+
+ C=0 M=0 Y=0 K=60
+ RGB
+ PROCESS
+ 137
+ 137
+ 137
+
+
+ C=0 M=0 Y=0 K=50
+ RGB
+ PROCESS
+ 159
+ 160
+ 160
+
+
+ C=0 M=0 Y=0 K=40
+ RGB
+ PROCESS
+ 181
+ 181
+ 182
+
+
+ C=0 M=0 Y=0 K=30
+ RGB
+ PROCESS
+ 201
+ 202
+ 202
+
+
+ C=0 M=0 Y=0 K=20
+ RGB
+ PROCESS
+ 220
+ 221
+ 221
+
+
+ C=0 M=0 Y=0 K=10
+ RGB
+ PROCESS
+ 239
+ 239
+ 239
+
+
+ C=0 M=0 Y=0 K=5
+ RGB
+ PROCESS
+ 247
+ 248
+ 248
+
+
+
+
+
+ 明亮
+ 1
+
+
+
+ C=0 M=100 Y=100 K=0
+ RGB
+ PROCESS
+ 230
+ 0
+ 18
+
+
+ C=0 M=75 Y=100 K=0
+ RGB
+ PROCESS
+ 235
+ 97
+ 0
+
+
+ C=0 M=10 Y=95 K=0
+ RGB
+ PROCESS
+ 255
+ 226
+ 0
+
+
+ C=85 M=10 Y=100 K=0
+ RGB
+ PROCESS
+ 0
+ 154
+ 62
+
+
+ C=100 M=90 Y=0 K=0
+ RGB
+ PROCESS
+ 11
+ 49
+ 143
+
+
+ C=60 M=90 Y=0 K=0
+ RGB
+ PROCESS
+ 126
+ 49
+ 142
+
+
+
+
+
+
+
+
+ Adobe PDF library 10.01
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+endstream
endobj
3 0 obj
<>
endobj
7 0 obj
<>/Resources<>/ExtGState<>/Properties<>>>/Thumb 32 0 R/TrimBox[0.0 0.0 600.0 200.0]/Type/Page>>
endobj
28 0 obj
<>stream
+HWۮ5}LNITg4*e粇]$T{e/_kxyW_*Sxy1sHQK?O/!?9cBᰭǙkLÙ[-gRz{8S](yKX)̻
b!XL
+^p*E@%2.-BɱlfST:~9~fC[ye:G\!*)
Ct-
+]C#-v2