-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
176 lines (152 loc) · 6.51 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package main
import (
"crypto/tls"
"fmt"
log "github.com/sirupsen/logrus"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/sohlich/elogrus.v2"
"gopkg.in/olivere/elastic.v5"
"gopkg.in/urfave/cli.v1"
"io"
"net/http"
"os"
"time"
)
var pac = `// ESTE ES EL ARCHIVO PAC/WPAD.DAT DE LA UNIVERSIDAD DISTRITAL
// FRANCISCO JOSE DE CALDAS.
// ESTE ARCHIVO REALIZA LA CONFIGURACION AUTOMATICA DE LA MAYORIA DE LOS
// NAVEGADORES PARA MAS INFORMACION VISITAR http://findproxyforurl.com/
function FindProxyForURL(url, host) {
// LA ESTRATEGIA DE FAIL-OVER EN CASO DE QUE NO SE PUEDA ESTABLECER UNA
// CONEXION CON EL PROXY ES HACER CONEXION DIRECTA (DIRECT)
var defaultProxy = "PROXY 10.20.4.15:3128; DIRECT";
// EXCEPCION OFICINA ASESORA DE SISTEMAS
// LA OFICINA ASESORA DE SISTEMAS TIENE UN DOMINIO EL CUAL ES ATENDIDO POR FUERA
// DE LA RED LOCAL, ESTE DEBE REDIRIGIRSE A TRAVES DEL PROXY
if (shExpMatch(host, "*.portaloas.udistrital.edu.co")) {
return defaultProxy;
}
// EXCEPCION AULAS VIRTUALES
// AULAS VIRTUALES SE ENCUENTRA ALOJADO POR FUERA DE LA RED LOCAL, DEBE UTILIZAR PROXY
if (dnsDomainIs(host, "aulasvirtuales.udistrital.edu.co")) {
return defaultProxy;
}
// CUALQUIER PETICION DESDE EL NAVEGADOR A DOMINIOS QUE TERMINEN EN
// .udistrital.edu.co O .udistritaloas.edu.co O .local[domain] NO SE ENVIARA A
// TRAVES DEL PROXY, QUIERE DECIR QUE CONECTARAN DIRECTAMENTE A TRAVES DE LA
// RED LOCAL, SIEMPRE Y CUANDO LOS CLIENTES PUEDAN RESOLVER ESTOS NOMBRES CON
// CONFIGURACION ACTUAL DE DNS Y QUE EXISTA UNA RUTA EN LA RED QUE LOS PUEDA
// CONECTAR; ES DECIR ACTUARA COMO SI EL PROXY SE HUBIERA DESHABILITADO
// MANUALMENTE. ESTA CONDICION SE BASA EN LA DIRECCION QUE SE VISITA EN LA
// BARRA DE DIRECCIONES Y SE EVALUA ANTES DE QUE OCURRA CUALQUIER CONEXION O
// RESOLUCION DE NOMBRE POR PARTE DEL NAVEGADOR
// LAS EXCEPCIONES A ESTA REGLA GENERAL DEBERÁN INSERTARSE ANTES DE ESTO
if (shExpMatch(host, "127.0.0.1") || // LOOPBACK
shExpMatch(host, "udistrital.infointelligen.com") || // PETICION UDNET 2018-04-06
shExpMatch(host, "*.local") || // UN DOMINIO MUY COMUN USADO PARA DESARROLLO
shExpMatch(host, "*.localdomain") || // UN DOMINIO COMUN USADO POR DEFECTO
shExpMatch(host, "*.nip.io") || // NIP ES UN CLON DE XIP
shExpMatch(host, "*.xip.io") || // XIP UN SERVICIO QUE MAPEA DOMINIOS COMODIN
shExpMatch(host, "*.udistrital.edu.co") || // DOMINIO OFICIAL DE LA UNIVERSIDAD
shExpMatch(host, "*.udistritaloas.edu.co") // DOMINIO NO OFICIAL DE LA OFICINA ASESORA DE SISTEMAS
) {
return "DIRECT";
}
// CUALQUIER PETICION QUE RESUELVA EL NOMBRE DNS A UNA IP LOCAL (ES DECIR
// CUALQUIER IP DEL ESPACIO PRIVADO DE IPV4) NO SERA ENVIADA A TRAVES DEL PROXY
// LAS EXCEPCIONES A ESTA REGLA GENERAL DEBERÁN INSERTARSE ANTES DE ESTO
var resolved_ip = dnsResolve(host);
if (isInNet(resolved_ip, "10.0.0.0", "255.0.0.0") || // UNA RED DE CLASE A
isInNet(resolved_ip, "172.16.0.0", "255.240.0.0") || // 16 REDES DE CLASE B
isInNet(resolved_ip, "192.168.0.0", "255.255.0.0") || // 256 REDES DE CLASE C
isInNet(resolved_ip, "169.254.0.0", "255.255.0.0") || // LINK-LOCAL RFC3927
isInNet(resolved_ip, "192.0.2.0", "255.255.255.0") || // TEST-NET RFC3330
isInNet(resolved_ip, "127.0.0.0", "255.0.0.0") // LOOPBACK
) {
return "DIRECT";
}
// CUALQUIER PETICION ENVIADA A UN HOST NO CALIFICADO (POR EJEMPLO http://www/ O
// https://mail/) NO SERA ENVIADA A TRAVES DEL PROXY
if (isPlainHostName(host)) {
return "DIRECT";
}
// SI NINGUNA DE LAS ANTERIORES CONDICIONES ANTERIORES APLICAN SE USARA EL PROXY
// POR DEFECTO
return defaultProxy;
}
// FIN`
func main() {
app := cli.NewApp()
app.Action = action
app.Flags = []cli.Flag{
cli.StringFlag{Name: "listen,l", Value: ":80", EnvVar: "UDPAC_LISTEN"},
cli.StringFlag{Name: "es-server", Value: "https://zabbix.udistritaloas.edu.co:9443/"},
cli.StringFlag{Name: "es-user", Value: "udnet"},
cli.StringFlag{Name: "es-pass", EnvVar: "UDPAC_ES_PASS"},
cli.BoolFlag{Name: "es-secure"},
cli.StringFlag{Name: "es-hostname", Value: "udpac"},
cli.StringFlag{Name: "es-index-prefix", Value: "udnet-"},
cli.Uint64Flag{Name: "racy-counter-mod", Value: 1000000},
cli.DurationFlag{Name: "es-index-duration", Value: 23*time.Hour + 59*time.Minute},
cli.StringFlag{Name: "es-index-layout", Value: "2006.01.02"},
}
app.Run(os.Args)
}
func action(ctx *cli.Context) {
var err error
var racyCounter uint64
logctx := log.WithFields(log.Fields{})
logctx.Info("INICIANDO UDPAC")
ticker := time.NewTicker(ctx.Duration("es-index-duration"))
config_es := func() {
logctx.Info("CONFIGURANDO ELASTICSEARCH")
client := &elastic.Client{}
hook := &elogrus.ElasticHook{}
es_index := ctx.String("es-index-prefix") + time.Now().Format(ctx.String("es-index-layout"))
if client, err = elastic.NewClient(
elastic.SetURL(ctx.String("es-server")),
elastic.SetBasicAuth(ctx.String("es-user"), ctx.String("es-pass")),
elastic.SetSniff(false),
elastic.SetMaxRetries(10),
elastic.SetHttpClient(&http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: !ctx.Bool("es-secure")}}})); err != nil {
logctx.Error("ERROR OBTENIENDO CLIENTE ES: " + err.Error())
} else if hook, err = elogrus.NewElasticHook(client, ctx.String("es-hostname"), log.DebugLevel, es_index); err != nil {
logctx.Error("ERROR EN HOOK:" + err.Error())
} else {
log.StandardLogger().Hooks = make(log.LevelHooks)
log.AddHook(hook)
}
}
config_es()
go func() {
for {
select {
case <-ticker.C:
config_es()
}
}
}()
logctx.Info("CONFIGURANDO PROMETHEUS")
pacServeCounter := prometheus.NewCounter(prometheus.CounterOpts{
Help: "Número de veces que se ha servido el archivo PAC",
Name: "pac_serve",
})
if err = prometheus.Register(pacServeCounter); err != nil {
logctx.Error("ERROR CONFIGURANDO PROMETHEUS: " + err.Error())
}
logctx.Info("CONFIGURANDO SERVIDOR HTTP")
http.Handle("/metrics", prometheus.Handler())
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/x-ns-proxy-autoconfig")
io.WriteString(w, pac)
pacServeCounter.Inc()
// esto es una mala idea
racyCounter = racyCounter + 1
if racyCounter%ctx.Uint64("racy-counter-mod") == 0 {
log.WithField("count", racyCounter).Info(fmt.Sprintf("Another %d happy customers", ctx.Uint64("racy-counter-mod")))
}
})
listen := ctx.String("listen")
logctx.Info("INICIANDO SERVIDOR DE PAC/WPAD.DAT EN " + listen)
logctx.Fatal(http.ListenAndServe(listen, nil))
}