How to add CipherSuites to grpc-go + tls?

951 views
Skip to first unread message

Constantine Vassilev

unread,
Sep 13, 2015, 2:26:05 PM9/13/15
to grpc.io
I need to add 

CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
},

to grpc-go server. 

How to do that?

Qi Zhao

unread,
Sep 13, 2015, 3:10:15 PM9/13/15
to Constantine Vassilev, grpc.io
You can use https://github.com/grpc/grpc-go/blob/master/credentials/credentials.go#L202 to create your credentials and pass it to the server instead of using NewServerTLSFromCert or NewServerTLSFromFile convenience functions.

--
You received this message because you are subscribed to the Google Groups "grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+u...@googlegroups.com.
To post to this group, send email to grp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/b4615a77-ec37-4d61-ad1b-3343fb74bf31%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 13, 2015, 3:15:10 PM9/13/15
to grpc.io, ths...@gmail.com
Thank you. Could you please post an example how to do that?

Constantine Vassilev

unread,
Sep 13, 2015, 3:25:21 PM9/13/15
to grpc.io, ths...@gmail.com
here is what I came up with:
not sure what to do with grpc.Creds(crews)

cert, err := tls.LoadX509KeyPair(runPath+"/cert.pem", runPath+"/key.pem")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}

config := &tls.Config{
Rand:         rand.Reader,
Certificates: []tls.Certificate{cert},
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
},
}
lis, err := net.Listen("tcp", fmt.Sprintf("%s:%s", addr, port))
if err != nil {
grpclog.Fatalf("failed to listen: %v", err)
}
var opts []grpc.ServerOption
credentials.NewTLS(config)

creds, err := credentials.NewServerTLSFromFile(runPath+"/cert.pem", runPath+"/key.pem")
if err != nil {
grpclog.Fatalf("Failed to generate credentials %v", err)
}
opts = []grpc.ServerOption{grpc.Creds(creds)}
// NewServer creates a gRPC server which has no service registered and has not
// started to accept requests yet.
grpcServer := grpc.NewServer(opts...)
// RegisterService register a service and its implementation to the gRPC
// server. Called from the IDL generated code. This must be called before
// invoking Serve.
// Serve accepts incoming connections on the listener lis, creating a new
// ServerTransport and service goroutine for each. The service goroutines
// read gRPC request and then call the registered handlers to reply to them.
// Service returns when lis.Accept fails.

pb.RegisterTCServiceServer(grpcServer, &grpcTCServer{})
grpcServer.Serve(lis)

Constantine Vassilev

unread,
Sep 13, 2015, 3:31:32 PM9/13/15
to grpc.io, ths...@gmail.com
Looks like this is working:


cert, err := tls.LoadX509KeyPair(runPath+"/cert.pem", runPath+"/key.pem")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}

config := &tls.Config{
Rand:         rand.Reader,
Certificates: []tls.Certificate{cert},
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
},
}
lis, err := net.Listen("tcp", fmt.Sprintf("%s:%s", addr, port))
if err != nil {
grpclog.Fatalf("failed to listen: %v", err)
}
var opts []grpc.ServerOption
creds := credentials.NewTLS(config)

Qi Zhao

unread,
Sep 13, 2015, 3:32:16 PM9/13/15
to Constantine Vassilev, grpc.io
Yup, u got it.


For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 13, 2015, 5:44:44 PM9/13/15
to grpc.io, ths...@gmail.com
Now next task is - how to make it work with ipv6?
I have an ipv6 , set it up the AAAA in GoDaddy
to point to it. How to make sure it will work with ipv6?

Qi Zhao

unread,
Sep 13, 2015, 6:28:33 PM9/13/15
to Constantine Vassilev, grpc.io
On Sun, Sep 13, 2015 at 2:44 PM, Constantine Vassilev <ths...@gmail.com> wrote:
Now next task is - how to make it work with ipv6?
I have an ipv6 , set it up the AAAA in GoDaddy
to point to it. How to make sure it will work with ipv6?
golang net has supported ipv6 already so that I think it simply works. 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 1:13:47 PM9/16/15
to grpc.io, ths...@gmail.com
I tested my server with www.ssllabs.com
For the ipv6 address I get a message:
Unable to connect to server 
For the ipv4 address passed all tests with grade A.

Somethings wrong with ipv6 configuration.

Qi Zhao

unread,
Sep 16, 2015, 1:32:20 PM9/16/15
to Constantine Vassilev, grpc.io
How is the DNS configured? What is the name resolution result of www.ssllabs.com?


For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 1:36:54 PM9/16/15
to grpc.io, ths...@gmail.com
Could you please tell me what you mean?

>How is the DNS configured?
Where to look for to tell you?

>What is the name resolution result of www.ssllabs.com?
Where in the report?

Qi Zhao

unread,
Sep 16, 2015, 1:38:22 PM9/16/15
to Constantine Vassilev, grpc.io
Let me ask in another way. How did you verify ipv4 work but ipv6 not work?


For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 1:42:13 PM9/16/15
to grpc.io, ths...@gmail.com
I am using www.ssllabs.com to see if it can find the ipv6 address.
I got Unable to connect to server for ipv6 address. ipv4 was found
and successfully graded.

I am building this for the new iOS 9. The requirements are that all apps
should support ipv6. Also I am using gRPC for web service.

Constantine Vassilev

unread,
Sep 16, 2015, 1:46:05 PM9/16/15
to grpc.io, ths...@gmail.com
The server is OS X and configured as follows:

Qi Zhao

unread,
Sep 16, 2015, 1:51:30 PM9/16/15
to Constantine Vassilev, grpc.io
I know nothing about ssllab. But I think the following steps can help you narrow down the problem"
i) make sure ipv6 is working on your OS X. You can probably start a golang http server (standard package, no grpc) on your machine and check. This step can make sure whether it is a problem of the ipv6 config or grpc;
ii) if i) works fine, did you let your gRPC server listen on ipv6 address? Can you show me the server side code which starts a gRPC server? 


For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 1:56:42 PM9/16/15
to grpc.io, ths...@gmail.com

Here is my code:

var addr string = "www.myserver.net"
var port string = "443"


cert, err := tls.LoadX509KeyPair(runPath+"/cert.pem", runPath+"/key.pem")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}
config := &tls.Config{
Rand:         rand.Reader,
Certificates: []tls.Certificate{cert},
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
},
}
lis, err := net.Listen("tcp", fmt.Sprintf("%s:%s", addr, port))
if err != nil {
grpclog.Fatalf("failed to listen: %v", err)
}
var opts []grpc.ServerOption
creds := credentials.NewTLS(config)
opts = []grpc.ServerOption{grpc.Creds(creds)}
grpcServer := grpc.NewServer(opts...)

pb.RegisterTCServiceServer(grpcServer, &grpcTCServer{})
grpcServer.Serve(lis)

Qi Zhao

unread,
Sep 16, 2015, 2:02:26 PM9/16/15
to Constantine Vassilev, grpc.io
a) step i) will be helpful for debugging;
b) can you run nslookup to get the address of "www.myserver.net" to verify you get a proper ipv6 address?


For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 2:11:38 PM9/16/15
to grpc.io, ths...@gmail.com
>i) make sure ipv6 is working on your OS X. 
I suppose Sslabs is probably not authoritative answer.
What do you recommend for i)?

b) -> I got it OK
nslookup -query=AAAA -> I got the AAAA record.
with ping6 I get the response OK.

Qi Zhao

unread,
Sep 16, 2015, 2:16:07 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 11:11 AM, Constantine Vassilev <ths...@gmail.com> wrote:
>i) make sure ipv6 is working on your OS X. 
I suppose Sslabs is probably not authoritative answer.
What do you recommend for i)?
I have no idea how your server is setup. But it is straightforward for me to replace your grpc server with a simplistic golang http server. And see if a http client can access your server on ipv6 address. 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 2:19:07 PM9/16/15
to grpc.io, ths...@gmail.com
Is my server code OK?
Do I need to specify lis, err := net.Listen("tcp" -> tcp6?

Qi Zhao

unread,
Sep 16, 2015, 2:22:39 PM9/16/15
to Constantine Vassilev, grpc.io
Yup, it is okay.

"tcp" is right thing to do. It will automatically switch between tcp4 and tcp6 according to the name resolution results.


For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Qi Zhao

unread,
Sep 16, 2015, 2:29:46 PM9/16/15
to Constantine Vassilev, grpc.io
another thing to try is to replace "www.myserver.net" with the real ipv6 address you pinged and see whether it works. It is highly possible you listen on an ipv4 address.
--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 2:33:21 PM9/16/15
to grpc.io, ths...@gmail.com
>replacing "www.myserver.net" with the real ipv6 address
I tried this  - it is not working
Also in real world the server needs to support both ipv4 and ipv6

> It is highly possible you listen on an ipv4 address.
but net.Listen("tcp" is supposed to automatically switch between tcp4 and tcp6?

Qi Zhao

unread,
Sep 16, 2015, 2:36:10 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 11:33 AM, Constantine Vassilev <ths...@gmail.com> wrote:
>replacing "www.myserver.net" with the real ipv6 address
I tried this  - it is not working
Also in real world the server needs to support both ipv4 and ipv6
Did you get the same error msg? 

> It is highly possible you listen on an ipv4 address.
but net.Listen("tcp" is supposed to automatically switch between tcp4 and tcp6?
depends on what name resolver gives to you. If it just gave u an ipv4 addr, you listen on a ipv4 address. Can u verify by printing Listener.Addr()? 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 2:42:10 PM9/16/15
to grpc.io, ths...@gmail.com
tcpAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%s", addr, port))
fmt.Printf("\nnet.Listen:tcpAddr.Network:%v, tcpAddr.String:%v\n", tcpAddr.Network(), tcpAddr.String())

I got ipv4 address (for the poset I canned it to 11.22.33.44)
net.Listen:tcpAddr.Network:tcp, tcpAddr.String:11.22.33.44:443

So "tcp" resolves to ipv4

Qi Zhao

unread,
Sep 16, 2015, 2:51:20 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 11:42 AM, Constantine Vassilev <ths...@gmail.com> wrote:
tcpAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%s", addr, port))
fmt.Printf("\nnet.Listen:tcpAddr.Network:%v, tcpAddr.String:%v\n", tcpAddr.Network(), tcpAddr.String())

I got ipv4 address (for the poset I canned it to 11.22.33.44)
net.Listen:tcpAddr.Network:tcp, tcpAddr.String:11.22.33.44:443

So "tcp" resolves to ipv4
So the root cause is that your server does not listen on that IPv6 address. It seems Listener gives the first ipv4 address from the name resolution.


For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 3:01:35 PM9/16/15
to grpc.io, ths...@gmail.com
So the right behavior of the server should be always listening to ipv6?

Qi Zhao

unread,
Sep 16, 2015, 3:08:40 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 12:01 PM, Constantine Vassilev <ths...@gmail.com> wrote:
So the right behavior of the server should be always listening to ipv6?
Yes if you really want to have a ipv6 specific server. I personally do not see the compelling reason to do that. You might have good reasons for your own service though. 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 3:17:55 PM9/16/15
to grpc.io, ths...@gmail.com
Apple requirements is new apps to support ipv6.

I tried this:
tcpAddr, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("%s:%s", addr, port))
lis, err := net.Listen(tcpAddr.Network(), tcpAddr.String())
now the server is listening to ipv6.

A test with Golang trying to connect:
conn, err := grpc.Dial(fmt.Sprintf("%s:%s", addr, port), opts...)
got the error:
grpc: ClientConn.resetTransport failed to create client transport: ...connection refused

from my iOS9 App with gRPC:

tcp_client_posix.c:149] socket error: connection refused


I suppose because I get ipv4 from the client name resolution but listening only to ipv6.

On reason can be that my ping on ipv4 gives faster response than ping6 on ipv6.

From the algorithm Apple is describing it tries to decide which one to use ipv4 or ipv6
and it depends from which is faster. In this case ipv4 is faster and probably that is 
why the name resolution gives back ipv4 both on the server and in device and the test Golang
program with .Dial


Qi Zhao

unread,
Sep 16, 2015, 3:26:56 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 12:17 PM, Constantine Vassilev <ths...@gmail.com> wrote:
Apple requirements is new apps to support ipv6.
Your app does support ipv6. As long as dns only returns ipv6 address, your app uses ipv6. :-) 

I tried this:
tcpAddr, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("%s:%s", addr, port))
lis, err := net.Listen(tcpAddr.Network(), tcpAddr.String())
now the server is listening to ipv6.

A test with Golang trying to connect:
conn, err := grpc.Dial(fmt.Sprintf("%s:%s", addr, port), opts...)
Can you simply dial the above ipv6 addr to make sure ipv6 works fine? 
got the error:
grpc: ClientConn.resetTransport failed to create client transport: ...connection refused

from my iOS9 App with gRPC:

tcp_client_posix.c:149] socket error: connection refused


I suppose because I get ipv4 from the client name resolution but listening only to ipv6.

On reason can be that my ping on ipv4 gives faster response than ping6 on ipv6. 
actually in golang, if name resolver returns multiple addresses, net.Dial will try to connect to them in parallel and choose the fastest one to be connected.  So in your case, my speculation is that the name resolver only returns ipv4 address (no ipv6 address at all). 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 3:32:30 PM9/16/15
to grpc.io, ths...@gmail.com


On Wednesday, September 16, 2015 at 12:26:56 PM UTC-7, Qi Zhao wrote:


On Wed, Sep 16, 2015 at 12:17 PM, Constantine Vassilev <ths...@gmail.com> wrote:
Apple requirements is new apps to support ipv6.
Your app does support ipv6. As long as dns only returns ipv6 address, your app uses ipv6. :-) 

I tried this:
tcpAddr, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("%s:%s", addr, port))
lis, err := net.Listen(tcpAddr.Network(), tcpAddr.String())
now the server is listening to ipv6.

A test with Golang trying to connect:
conn, err := grpc.Dial(fmt.Sprintf("%s:%s", addr, port), opts...)
Can you simply dial the above ipv6 addr to make sure ipv6 works fine? 

I cannot Dial directly with ipv6 address because I get transport: x509: cannot validate certificate for  because it doesn't contain any IP SANs"
 
got the error:
grpc: ClientConn.resetTransport failed to create client transport: ...connection refused

from my iOS9 App with gRPC:

tcp_client_posix.c:149] socket error: connection refused


I suppose because I get ipv4 from the client name resolution but listening only to ipv6.

On reason can be that my ping on ipv4 gives faster response than ping6 on ipv6. 
actually in golang, if name resolver returns multiple addresses, net.Dial will try to connect to them in parallel and choose the fastest one to be connected.  So in your case, my speculation is that the name resolver only returns ipv4 address (no ipv6 address at all). 

Name revolver in Golang server?
 
...

Qi Zhao

unread,
Sep 16, 2015, 3:37:56 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 12:32 PM, Constantine Vassilev <ths...@gmail.com> wrote:


On Wednesday, September 16, 2015 at 12:26:56 PM UTC-7, Qi Zhao wrote:


On Wed, Sep 16, 2015 at 12:17 PM, Constantine Vassilev <ths...@gmail.com> wrote:
Apple requirements is new apps to support ipv6.
Your app does support ipv6. As long as dns only returns ipv6 address, your app uses ipv6. :-) 

I tried this:
tcpAddr, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("%s:%s", addr, port))
lis, err := net.Listen(tcpAddr.Network(), tcpAddr.String())
now the server is listening to ipv6.

A test with Golang trying to connect:
conn, err := grpc.Dial(fmt.Sprintf("%s:%s", addr, port), opts...)
Can you simply dial the above ipv6 addr to make sure ipv6 works fine? 

I cannot Dial directly with ipv6 address because I get transport: x509: cannot validate certificate for  because it doesn't contain any IP SANs"
This is a separate issue. To debug, you can disable tls/ssl anyways. 
 
got the error:
grpc: ClientConn.resetTransport failed to create client transport: ...connection refused

from my iOS9 App with gRPC:

tcp_client_posix.c:149] socket error: connection refused


I suppose because I get ipv4 from the client name resolution but listening only to ipv6.

On reason can be that my ping on ipv4 gives faster response than ping6 on ipv6. 
actually in golang, if name resolver returns multiple addresses, net.Dial will try to connect to them in parallel and choose the fastest one to be connected.  So in your case, my speculation is that the name resolver only returns ipv4 address (no ipv6 address at all). 

Name revolver in Golang server?
I meant DNS server. We get the point which is completely out of scope of gRPC already. :-) gRPC does not do anything special for ipv6. Any problem you have here applies to other non-gRPC scenarios (e.g., http). 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 3:50:35 PM9/16/15
to grpc.io, ths...@gmail.com
I think the server should be able to listen to both
ipv6 and ipv4. How to do that?
...

Qi Zhao

unread,
Sep 16, 2015, 3:54:03 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 12:50 PM, Constantine Vassilev <ths...@gmail.com> wrote:
I think the server should be able to listen to both
ipv6 and ipv4. How to do that?
For now, you can create 2 listeners (one for ipv4 and one for ipv6, hardcode ip addresses) and serve them. 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 4:00:17 PM9/16/15
to grpc.io, ths...@gmail.com
how I would do that in code?

I suppose something like this:

lis, _ := net.Listen("tcp4", fmt.Sprintf("%s:%s", addr, port))
lis2, _ := net.Listen("tcp6", fmt.Sprintf("%s:%s", addr, port))
var opts []grpc.ServerOption
creds := credentials.NewTLS(config)
opts = []grpc.ServerOption{grpc.Creds(creds)}
grpcServer := grpc.NewServer(opts...)

pb.RegisterTCServiceServer(grpcServer, &grpcTCServer{})
grpcServer.Serve(lis)
grpcServer.Serve(lis2)
...

Qi Zhao

unread,
Sep 16, 2015, 4:02:28 PM9/16/15
to Constantine Vassilev, grpc.io
On Wed, Sep 16, 2015 at 1:00 PM, Constantine Vassilev <ths...@gmail.com> wrote:
how I would do that in code?

I suppose something like this:

lis, _ := net.Listen("tcp4", fmt.Sprintf("%s:%s", addr, port))
lis2, _ := net.Listen("tcp6", fmt.Sprintf("%s:%s", addr, port))
The above 2 addresses are not same. One is ipv4. The other is ipv6. 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 4:08:35 PM9/16/15
to grpc.io, ths...@gmail.com
here is how I corrected it:

fmt.Printf("\nnet.Listen:tcpAddr.Network:%v, tcpAddr.String:%v\n", tcpAddr4.Network(), tcpAddr4.String())
fmt.Printf("\nnet.Listen:tcpAddr.Network:%v, tcpAddr.String:%v\n", tcpAddr6.Network(), tcpAddr6.String())

lis4, err := net.Listen(tcpAddr4.Network(), tcpAddr4.String())
lis6, err := net.Listen(tcpAddr6.Network(), tcpAddr6.String())
if err != nil {
grpclog.Fatalf("failed to listen: %v", err)
}
var opts []grpc.ServerOption
creds := credentials.NewTLS(config)
opts = []grpc.ServerOption{grpc.Creds(creds)}

grpcServer4 := grpc.NewServer(opts...)
pb.RegisterTCServiceServer(grpcServer4, &grpcTCServer{})
grpcServer4.Serve(lis4)

grpcServer6 := grpc.NewServer(opts...)
pb.RegisterTCServiceServer(grpcServer6, &grpcTCServer{})
grpcServer6.Serve(lis6)


os it the right thing to do?
...

Constantine Vassilev

unread,
Sep 16, 2015, 4:10:17 PM9/16/15
to grpc.io, ths...@gmail.com
here is the full code:


config := &tls.Config{
Rand:         rand.Reader,
Certificates: []tls.Certificate{cert},
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
},
}
tcpAddr4, _ := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%s", addr, port))
tcpAddr6, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("%s:%s", addr, port))
...

Qi Zhao

unread,
Sep 16, 2015, 6:15:25 PM9/16/15
to Constantine Vassilev, grpc.io
You do not need to have two grpc servers. Instead, lis4 and lis6 can be served by the same server. 

For more options, visit https://groups.google.com/d/optout.



--
Thanks,
-Qi

Constantine Vassilev

unread,
Sep 16, 2015, 6:27:55 PM9/16/15
to grpc.io, ths...@gmail.com
this was good suggestion. here the final code:

config := &tls.Config{
Rand:         rand.Reader,
Certificates: []tls.Certificate{cert},
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
},
}
tcpAddr4, _ := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%s", addr, port))
tcpAddr6, _ := net.ResolveTCPAddr("tcp6", fmt.Sprintf("%s:%s", addr, port))
fmt.Printf("\nnet.Listen:tcpAddr.Network:%v, tcpAddr.String:%v\n", tcpAddr4.Network(), tcpAddr4.String())
fmt.Printf("\nnet.Listen:tcpAddr.Network:%v, tcpAddr.String:%v\n", tcpAddr6.Network(), tcpAddr6.String())

lis4, err4 := net.Listen(tcpAddr4.Network(), tcpAddr4.String())
if err4 != nil {
grpclog.Fatalf("failed to listen: %v", err4)
}
lis6, err6 := net.Listen(tcpAddr6.Network(), tcpAddr6.String())
if err6 != nil {
grpclog.Fatalf("failed to listen: %v", err6)
}
var opts []grpc.ServerOption
creds := credentials.NewTLS(config)
opts = []grpc.ServerOption{grpc.Creds(creds)}

grpcServer := grpc.NewServer(opts...)
pb.RegisterTCServiceServer(grpcServer, &grpcTCServer{})
grpcServer.Serve(lis4)
grpcServer.Serve(lis6)
...
Message has been deleted

Constantine Vassilev

unread,
Sep 19, 2015, 6:25:58 PM9/19/15
to grpc.io, ths...@gmail.com
How I would know which connection was served: ipv4 or ipv6?

I made ipv6 test environment according:
...

Paul Marks

unread,
Sep 21, 2015, 8:26:34 PM9/21/15
to Constantine Vassilev, grpc.io
On Sun, Sep 13, 2015 at 12:25 PM, Constantine Vassilev
<ths...@gmail.com> wrote:
> lis, err := net.Listen("tcp", fmt.Sprintf("%s:%s", addr, port))

When listening, just leave the host blank:
http://www.grpc.io/docs/tutorials/basic/go.html#starting-the-server

In most environments, this will create an IPv4+IPv6 socket.

Constantine Vassilev

unread,
Sep 22, 2015, 12:43:44 AM9/22/15
to grpc.io, ths...@gmail.com
It is little more complicated. On the server I need to support
also a legacy server listening to different host address.
So I need to specify the address.

So far I implemented the Apple requirement for test environment
setting up a local IPv6 DNS64/NAT64 network with my Mac Book Pro.
All 4 cases of gRPC communication are working.

the only concern I am having is that 
fir the new OS X 10.11 and iOS 9 Apple is recommending
using higher level 
NSURLSession and CFNetwork- layer APIs.

Not sure what Objective-C gRPC is using.

Jorge Canizales

unread,
Sep 22, 2015, 1:35:04 AM9/22/15
to grpc.io, ths...@gmail.com


On Monday, September 21, 2015 at 9:43:44 PM UTC-7, Constantine Vassilev wrote:
It is little more complicated. On the server I need to support
also a legacy server listening to different host address.
So I need to specify the address.

So far I implemented the Apple requirement for test environment
setting up a local IPv6 DNS64/NAT64 network with my Mac Book Pro.
All 4 cases of gRPC communication are working.

the only concern I am having is that 
fir the new OS X 10.11 and iOS 9 Apple is recommending
using higher level 
NSURLSession and CFNetwork- layer APIs.

Not sure what Objective-C gRPC is using.

This has always been Apple's recommendation, and with good reasons. Unfortunately, neither Cocoa (NSURLSession) nor CFNetworking expose HTTP/2 interfaces that one would need to implement gRPC. Even if underneath the interface their client now uses HTTP/2, what's exposed to the developer are only HTTP/1.1 semantics. So Objective-C gRPC is layered on top of the C gRPC library, which uses POSIX sockets. However the C library resolves addresses, that's how the Objective-C library resolves them.

Jorge Canizales

unread,
Sep 22, 2015, 1:35:53 AM9/22/15
to grpc.io, ths...@gmail.com
I mean that whichever way one does it, so does the other.

Constantine Vassilev

unread,
Sep 22, 2015, 6:20:50 PM9/22/15
to grpc.io, ths...@gmail.com
I believe iOS 9 is supporting HTTP/2 using NSURLSession and CFNetwork.


On Monday, September 21, 2015 at 10:35:04 PM UTC-7, Jorge Canizales wrote:

Constantine Vassilev

unread,
Oct 5, 2015, 6:07:00 PM10/5/15
to grpc.io, ths...@gmail.com
how to do the same with http.Server?
...

Jorge Canizales

unread,
Oct 26, 2015, 8:30:42 PM10/26/15
to grpc.io, ths...@gmail.com
Hi Constantine,

even if NSURLSession and CFNetwork in iOS9 use HTTP/2 under the hood, they don't expose the HTTP/2-specific interfaces one would require to implement gRPC on top of them. What's exposed to the developer are only HTTP/1.1 semantics: There's no full-duplex streaming, and no documented support for trailers nor flow-control. We are filing a Radar with Apple to ask for those features to be added to NSURLSession.

Alternatively, one could try to write an "almost-working" gRPC client on top of today's NSURLSession. But e.g. Chrome's network stack on iOS uses POSIX sockets too, with great results; and that also gives them the ability to test new protocols like QUIC.

Cheers,
Jorge

Jorge Canizales

unread,
Oct 26, 2015, 8:32:02 PM10/26/15
to grpc.io, ths...@gmail.com, Qi Zhao
CC: Qi to answer this parallel thread within this thread :)

Constantine Vassilev

unread,
Oct 26, 2015, 9:07:07 PM10/26/15
to grpc.io, ths...@gmail.com
I spend a lot of time on gRPC, made a working server in Golang and a client
in Swift for iOS 9, following Apple requirements.

The amount of time required to make it work is a lot. The problem is I thought
I made it and after weeks of testing mentioned that with WiFi 
sometimes it is working sometimes it is not. Got deeper and understood it is
not using a standard way to communicate. If it not using NSURLSession or CFNetwork 
the ipv6 requirement from Apple will not work. The App would be not approved -
no point of using gRPC at all.

Then I made following setup - a Golang server listening to both ipv4 and ipv6. 
Protobuf 3.0 for generating the libraries for Golang server and Swift for device,
CoreData for in device DB, iCloud DB for backup and sharing. As you see -
3 different technologies are needed for a practical App. They need to be simple
enough. gRPC is anything but simple.

With this setup Request/Response takes ~200ms to travel back and forth in base64. 
~50 microseconds for Protobuf libraries to parse, etc. The data size is ~10KB This is the simplest 
possible case and it is working just perfectly using NSURLSession. There is always 
connectivity, working with ipv4 and ipv6. Tested with Apple ipv6 setup many times.
For mobile I would be happy with response time of 2-5 Secs. I am getting less than a 
half a second! I don't think it can be faster than that if you use HTTP/2.

Now - gRPC is overkill for such cases which are in my experience 90% of the time.
Streaming, etc - no need for these cases, hard to sell them as an argument to 
use gRPC in real world. Real world is simple web services  - Request/Response.
With Swift blocks can be made asynchronous too.
I do web services for living 10 years already. .NET, Vb.NET, C, XML you name it.
For mobile is needed different setup but experience is important.

This setup will pass the App Review, no hidden uncertainties. By the way my 
Apps a Waiting for Review 7 days, In Review for ~1 hour Ready to Sell in ~2 hours.
Because I rely for critical things like connectivity on Apple technologies.

Another issues: with gRPC on the device I should switch off bit code for the entire project.
This is a big problem. This library is not made specifically for iOS but tries 
to cover so many platforms, so long time still in Apha. 

On the device side what matter is I want to monetize
and have security against reverse engineering and this is iOS. 
Other platforms are irrelevant from this point of view.

My 2 cents.

--Constantine
Reply all
Reply to author
Forward
0 new messages