Skip to content

Commit 83ee119

Browse files
authored
Merge branch 'master' into ssh
2 parents 00487dc + 8abb71b commit 83ee119

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2053
-736
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,8 @@ tools/pathdb_dump/pathdb_dump
5151
netcat/netcat
5252
ssh/client/client
5353
ssh/server/server
54+
roughtime/timeclient/timeclient
55+
roughtime/timeserver/timeserver
56+
57+
# vscode workspace
58+
*.code-workspace

Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
.PHONY: all clean
22

33
ROOT_DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
4-
# TODO: missing roughtime/timeserver roughtime/timeclient
5-
SRCDIRS= helloworld sensorapp/sensorserver sensorapp/sensorfetcher camerapp/imageserver camerapp/imagefetcher bwtester/bwtestserver bwtester/bwtestclient webapp bat bat/example_server tools/pathdb_dump netcat ssh/client ssh/server
4+
SRCDIRS= helloworld sensorapp/sensorserver sensorapp/sensorfetcher camerapp/imageserver camerapp/imagefetcher bwtester/bwtestserver bwtester/bwtestclient webapp bat bat/example_server tools/pathdb_dump roughtime/timeserver roughtime/timeclient ssh/client ssh/server netcat
65
TARGETS = $(foreach D,$(SRCDIRS),$(D)/$(notdir $(D)))
76

87
all: $(TARGETS)
@@ -13,6 +12,9 @@ deps:
1312
clean:
1413
@$(foreach d,$(SRCDIRS),cd $(ROOT_DIR)/$(d) && go clean;)
1514

15+
install: all
16+
@$(foreach d,$(SRCDIRS), cd $(ROOT_DIR)/$(d); cp $(shell basename $(d)) ~/go/bin;)
17+
1618
# using eval to create as many rules as we have $TARGETS
1719
# each target corresponds to the binary file name (e.g. sensorapp/sensorserver/sensorserver)
1820
define gobuild_tmpl =

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ More information on [SCION](https://www.scion-architecture.net/), and [tutorials
88

99
To build:
1010
1. run once the provided script `deps.sh` to set up the dependencies
11-
2. run `make` to build all projects
11+
2. run `make install` to build all projects and install into `$GOPATH/bin`
1212

1313

1414
## bat

bat/bat.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ var (
7474
)
7575

7676
func init() {
77-
7877
flag.BoolVar(&interactive, "in", false, "Lets user choose the path to destination")
7978
flag.BoolVar(&ver, "v", false, "Print Version Number")
8079
flag.BoolVar(&ver, "version", false, "Print Version Number")

bwtester/bwtestserver/bwtestserver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ func main() {
115115
// Create the SCION UDP socket
116116
if len(serverCCAddrStr) == 0 {
117117
serverCCAddr, err = scionutil.GetLocalhost()
118-
serverCCAddr.Host.L4 = addr.NewL4UDPInfo(uint16(serverPort))
119118
if err != nil {
120119
printUsage()
121-
LogFatal("Unable to start server", "err", err)
120+
LogFatal("Unable to start server, please provide the server address manually", "err", err)
122121
}
122+
serverCCAddr.Host.L4 = addr.NewL4UDPInfo(uint16(serverPort))
123123
} else {
124124
serverCCAddr, err = snet.AddrFromString(serverCCAddrStr)
125125
if err != nil {

camerapp/imageserver/imageserver.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ func main() {
155155
}
156156
} else {
157157
server, err = scionutil.GetLocalhost()
158-
server.Host.L4 = addr.NewL4UDPInfo(uint16(serverPort))
159158
check(err)
159+
server.Host.L4 = addr.NewL4UDPInfo(uint16(serverPort))
160160
}
161161

162162
if sciondFromIA {

lib/scionutil/hosts.go

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,39 @@ import (
1818
"bytes"
1919
"fmt"
2020
"io/ioutil"
21-
"log"
21+
"os"
22+
"path"
2223
"regexp"
2324
"strings"
25+
"time"
2426

27+
"github.com/netsec-ethz/rains/pkg/rains"
2528
libaddr "github.com/scionproto/scion/go/lib/addr"
29+
"github.com/scionproto/scion/go/lib/snet"
2630
)
2731

2832
type scionAddress struct {
2933
ia libaddr.IA
3034
l3 libaddr.HostAddr
3135
}
3236

37+
// hosts file
3338
var (
3439
hostFilePath = "/etc/hosts"
3540
addrRegexp = regexp.MustCompile(`^(?P<ia>\d+-[\d:A-Fa-f]+),\[(?P<host>[^\]]+)\]`)
36-
hosts map[string]scionAddress // hostname -> scionAddress
37-
revHosts map[string][]string // SCION address w/o port -> hostnames
41+
hosts = make(map[string]scionAddress) // hostname -> scionAddress
42+
revHosts = make(map[string][]string) // SCION address w/o port -> hostnames
43+
)
44+
45+
// RAINS
46+
var (
47+
rainsConfigPath = path.Join(os.Getenv("SC"), "gen", "rains.cfg")
48+
ctx = "." // use global context
49+
qType = rains.OTScionAddr4 // request SCION IPv4 addresses
50+
qOpts = []rains.Option{} // no options
51+
expire = 5 * time.Minute // sensible expiry date?
52+
timeout = 500 * time.Millisecond // timeout for query
53+
rainsServer *snet.Addr // resolver address
3854
)
3955

4056
const (
@@ -43,19 +59,20 @@ const (
4359
)
4460

4561
func init() {
62+
// parse hosts file
4663
hostsFile, err := readHostsFile()
47-
if err != nil {
48-
hostsFile = []byte{}
49-
}
50-
parseHostsFile(hostsFile)
51-
if err != nil {
52-
log.Fatal(err)
64+
if err == nil {
65+
parseHostsFile(hostsFile)
5366
}
67+
68+
// read RAINS server address
69+
rainsServer = readRainsConfig()
5470
}
5571

5672
// AddHost adds a host to the map of known hosts
5773
// An error is returned if the address has a wrong format or
5874
// the hostname already exists
75+
// The added host will not persist between program executions
5976
func AddHost(hostname, address string) error {
6077
if addrs, ok := hosts[hostname]; ok {
6178
return fmt.Errorf("Host %q already exists, address(es): %v", hostname, addrs)
@@ -72,14 +89,35 @@ func AddHost(hostname, address string) error {
7289

7390
// GetHostByName returns the IA and HostAddr corresponding to hostname
7491
func GetHostByName(hostname string) (libaddr.IA, libaddr.HostAddr, error) {
92+
// try to resolve hostname locally
7593
addr, ok := hosts[hostname]
76-
if !ok {
77-
return libaddr.IA{}, nil, fmt.Errorf("Address for host %q not found", hostname)
94+
if ok {
95+
return addr.ia, addr.l3, nil
96+
}
97+
98+
if rainsServer == nil {
99+
return libaddr.IA{}, nil, fmt.Errorf("Could not resolve %q, no RAINS server configured", hostname)
78100
}
79-
return addr.ia, addr.l3, nil
101+
102+
// fall back to RAINS
103+
104+
// TODO(chaehni): This call can sometimes cause a timeout even though the server is reachable (see issue #221)
105+
// The timeout value has been decreased to counter this behavior until the problem is resolved.
106+
reply, err := rains.Query(hostname, ctx, []rains.Type{qType}, qOpts, expire, timeout, rainsServer)
107+
if err != nil {
108+
return libaddr.IA{}, nil, fmt.Errorf("Address for host %q not found: %v", hostname, err)
109+
}
110+
scionAddr, err := addrFromString(reply[qType])
111+
if err != nil {
112+
return libaddr.IA{}, nil, fmt.Errorf("Address for host %q invalid: %v", hostname, err)
113+
}
114+
115+
return scionAddr.ia, scionAddr.l3, nil
116+
80117
}
81118

82119
// GetHostnamesByAddress returns the hostnames corresponding to address
120+
// TODO: (chaehni) RAINS address query to resolve address to name
83121
func GetHostnamesByAddress(address string) ([]string, error) {
84122
match := addrRegexp.FindString(address)
85123
host, ok := revHosts[match]
@@ -98,8 +136,6 @@ func readHostsFile() ([]byte, error) {
98136
}
99137

100138
func parseHostsFile(hostsFile []byte) {
101-
hosts = make(map[string]scionAddress)
102-
revHosts = make(map[string][]string)
103139
lines := bytes.Split(hostsFile, []byte("\n"))
104140
for _, line := range lines {
105141
fields := strings.Fields(string(line))
@@ -124,8 +160,23 @@ func parseHostsFile(hostsFile []byte) {
124160
}
125161
}
126162

163+
func readRainsConfig() *snet.Addr {
164+
bs, err := ioutil.ReadFile(rainsConfigPath)
165+
if err != nil {
166+
return nil
167+
}
168+
addr, err := snet.AddrFromString(strings.TrimSpace(string(bs)))
169+
if err != nil {
170+
return nil
171+
}
172+
return addr
173+
}
174+
127175
func addrFromString(addr string) (scionAddress, error) {
128176
parts := addrRegexp.FindStringSubmatch(addr)
177+
if parts == nil {
178+
return scionAddress{}, fmt.Errorf("No valid SCION address: %q", addr)
179+
}
129180
ia, err := libaddr.IAFromString(parts[iaIndex])
130181
if err != nil {
131182
return scionAddress{}, fmt.Errorf("Invalid IA string: %v", parts[iaIndex])

lib/scionutil/initialization.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ func GetDefaultDispatcher() string {
6767
// GetLocalhost returns a local SCION address an application can bind to
6868
func GetLocalhost() (*snet.Addr, error) {
6969
str, err := GetLocalhostString()
70+
if err != nil {
71+
return nil, err
72+
}
7073
addr, err := snet.AddrFromString(str)
7174
if err != nil {
7275
return nil, err

lib/shttp/transport.go

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@ package shttp
1919

2020
import (
2121
"crypto/tls"
22+
"errors"
23+
"fmt"
2224
"net"
2325
"net/http"
26+
"net/url"
2427
"strconv"
28+
"strings"
2529
"sync"
2630

2731
"github.com/lucas-clemente/quic-go"
2832
"github.com/lucas-clemente/quic-go/h2quic"
2933
"github.com/netsec-ethz/scion-apps/lib/scionutil"
30-
libaddr "github.com/scionproto/scion/go/lib/addr"
34+
"github.com/scionproto/scion/go/lib/addr"
3135
"github.com/scionproto/scion/go/lib/snet"
3236
// "github.com/scionproto/scion/go/lib/snet/squic"
3337
)
@@ -91,9 +95,20 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*h
9195
return nil, initErr
9296
}
9397

98+
// If req.URL.Host is a SCION address, we need to mangle it so it passes through
99+
// h2quic without tripping up.
100+
raddr, err := snet.AddrFromString(req.URL.Host)
101+
if err == nil {
102+
tmp := *req
103+
tmp.URL = new(url.URL)
104+
*tmp.URL = *req.URL
105+
tmp.URL.Host = mangleSCIONAddr(raddr)
106+
req = &tmp
107+
}
108+
94109
// set the dial function and QuicConfig once for each Transport
95110
t.dialOnce.Do(func() {
96-
dial := func(network, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.Session, error) {
111+
dial := func(network, addrStr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.Session, error) {
97112

98113
/* TODO(chaehni):
99114
RequestConnectionIDOmission MUST not be set to 'true' when a connection is dialed using an existing net.PacketConn
@@ -105,20 +120,28 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*h
105120
*/
106121
cfg.RequestConnectionIDOmission = false
107122

108-
host, port, err := net.SplitHostPort(addr)
123+
host, port, err := net.SplitHostPort(addrStr)
109124
if err != nil {
110125
return nil, err
111126
}
112-
ia, l3, err := scionutil.GetHostByName(host)
127+
128+
var ia addr.IA
129+
var l3 addr.HostAddr
130+
if isMangledSCIONAddr(host) {
131+
ia, l3, err = unmangleSCIONAddr(host)
132+
} else {
133+
ia, l3, err = scionutil.GetHostByName(host)
134+
}
113135
if err != nil {
114136
return nil, err
115137
}
116138
p, err := strconv.ParseUint(port, 10, 16)
117139
if err != nil {
118140
p = 443
119141
}
120-
l4 := libaddr.NewL4UDPInfo(uint16(p))
121-
raddr := &snet.Addr{IA: ia, Host: &libaddr.AppAddr{L3: l3, L4: l4}}
142+
l4 := addr.NewL4UDPInfo(uint16(p))
143+
raddr := &snet.Addr{IA: ia, Host: &addr.AppAddr{L3: l3, L4: l4}}
144+
122145
return t.squicDialSCION(nil, t.LAddr, raddr, cfg)
123146
}
124147
t.rt = &h2quic.RoundTripper{
@@ -131,6 +154,48 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt h2quic.RoundTripOpt) (*h
131154
return t.rt.RoundTripOpt(req, opt)
132155
}
133156

157+
// mangleSCIONAddr encodes the given SCION address so that it can be safely
158+
// used in the host part of a URL.
159+
func mangleSCIONAddr(raddr *snet.Addr) string {
160+
161+
// The HostAddr will be either IPv4 or IPv6 (not a HostSVC-addr).
162+
// To make this a valid host string for a URL, replace : for IPv6 addresses by ~. There will
163+
// not be any other tildes, so no need to escape them.
164+
l3 := raddr.Host.L3.String()
165+
l3_mangled := strings.Replace(l3, ":", "~", -1)
166+
167+
u := fmt.Sprintf("__%s__%s__", raddr.IA.FileFmt(false), l3_mangled)
168+
if raddr.Host.L4 != nil {
169+
u += fmt.Sprintf(":%d", raddr.Host.L4.Port())
170+
}
171+
return u
172+
}
173+
174+
// isMangledSCIONAddr checks if this is an address previously encoded with mangleSCIONAddr
175+
// without port, *after* SplitHostPort has been applied.
176+
func isMangledSCIONAddr(host string) bool {
177+
178+
parts := strings.Split(host, "__")
179+
return len(parts) == 4 && len(parts[0]) == 0 && len(parts[3]) == 0
180+
}
181+
182+
// unmangleSCIONAddr decodes and parses a SCION-address previously encoded with mangleSCIONAddr
183+
// without port, i.e. *after* SplitHostPort has been applied.
184+
func unmangleSCIONAddr(host string) (addr.IA, addr.HostAddr, error) {
185+
186+
parts := strings.Split(host, "__")
187+
ia, err := addr.IAFromFileFmt(parts[1], false)
188+
if err != nil {
189+
return addr.IA{}, nil, err
190+
}
191+
l3_str := strings.Replace(parts[2], "~", ":", -1)
192+
l3 := addr.HostFromIPStr(l3_str)
193+
if l3 == nil {
194+
return addr.IA{}, nil, errors.New("Could not parse IP in SCION-address")
195+
}
196+
return ia, l3, nil
197+
}
198+
134199
// Close closes the QUIC connections that this RoundTripper has used
135200
func (t *Transport) Close() error {
136201
err := t.rt.Close()

netcat/README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@ A SCION port of the netcat process.
33

44

55
## Usage
6-
```./netcat <host> <port>```
6+
```
7+
./netcat <host> <port>
8+
./netcat -l <port>
9+
```
10+
11+
Remember to generate a TLS certificate first (this will generate them in the current working directory):
12+
```
13+
openssl req -newkey rsa:2048 -nodes -keyout ./key.pem -x509 -days 365 -out ./certificate.pem
14+
```
715

816
See `./netcat -h` for more.
917

0 commit comments

Comments
 (0)